cf 730i

题意:有n个人,每个人有两个能力值,选a个人用它的第一个能力值,b个人用它的第二个能力值,每个人只能选一次,求一个方案使得能力值之和最大,并输出选择方案.

题解:最小费用最大流,原点1向n个人每个人i+1连流量为1费用为0的边,在有两个点n+2和n+3,每个人i+1向点n+2连流量为1,费用为-能量值的边,向n+3连流量为1,费用为-能力值的边,n+2向汇点n+4连流量为a费用为0的边,n+3向汇点n+4连流量为b费用为0的边.

注意:应该在跑完了费用流之后再输出路径,因为在过程之后总有可能有反向边,所以无法在过程中就确定最终路径.跑完了费用流之后,如果某一条边反向流不为0即表示有流量经过.

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<climits>
  5 #include<queue>
  6 #include<cmath>
  7 #define MAXP 3010
  8 #define MAXE 40500
  9 #define MIN(a,b) (a<b?a:b)
 10 using namespace std;
 11 int n,m;
 12 struct Edge
 13 {
 14     int s,t,f,c,next;
 15 };
 16 class MCMF
 17 {
 18 public:
 19     MCMF(int s,int t);
 20     void insert(int s,int t,int f,int c);
 21     bool spfa();
 22     void mcmf();
 23     void print();
 24 private:
 25     bool *isq;
 26     int s,t;
 27     int *dist;
 28     int ent;
 29     int cost,flow;
 30     int *head;
 31     int *pre;
 32     Edge *edge;
 33 };
 34 MCMF::MCMF(int s,int t)
 35 {
 36     this->s=s;
 37     this->t=t;
 38     ent=0;
 39     cost=0;
 40     flow=0;
 41     isq=new bool [MAXP];
 42     dist=new int[MAXP];
 43     head=new int[MAXP];
 44     edge=new Edge[MAXE];
 45     pre=new int[MAXE];
 46     memset(head,-1,sizeof(int)*MAXP);
 47 }
 48 void MCMF::insert(int s,int t,int f,int c)
 49 {
 50     edge[ent].s=s;edge[ent].t=t;edge[ent].f=f;
 51     edge[ent].c=c;edge[ent].next=head[s];head[s]=ent++;
 52     edge[ent].s=t;edge[ent].t=s;edge[ent].f=0;
 53     edge[ent].c=-c;edge[ent].next=head[t];head[t]=ent++;
 54 }
 55 bool MCMF::spfa()
 56 {
 57     memset(pre,-1,sizeof(int)*MAXE);
 58     for(int i=1;i<=t;i++)
 59     {
 60         isq[i]=false;
 61         dist[i]=INT_MAX;
 62     }
 63     queue<int>q;
 64     q.push(s);
 65     isq[s]=true;
 66     dist[s]=0;
 67     while(!q.empty())
 68     {
 69         int temp1=q.front();
 70         q.pop();
 71         isq[temp1]=false;
 72         for(int i=head[temp1];i!=-1;i=edge[i].next)
 73         {
 74             int temp2=edge[i].t;
 75             if(edge[i].f&&edge[i].c+dist[temp1]<dist[temp2])
 76             {
 77                 dist[temp2]=edge[i].c+dist[temp1];
 78                 pre[temp2]=i;
 79                 if(!isq[temp2])
 80                     q.push(temp2);
 81             }
 82         }
 83     }
 84     return pre[t]!=-1;
 85 }
 86 void MCMF::mcmf()
 87 {
 88     while(spfa())
 89     {
 90         int minn=INT_MAX;
 91         for(int i=pre[t];i!=-1;i=pre[i])
 92         {
 93             minn=MIN(minn,edge[i].f);
 94             i=edge[i].s;
 95         }
 96         flow+=minn;
 97         for(int i=pre[t];i!=-1;i=pre[i])
 98         {
 99             edge[i].f-=minn;
100             edge[i^1].f+=minn;
101             i=edge[i].s;
102         }
103         cost+=minn*dist[t];
104     }
105     cout<<-cost<<endl;
106 }
107 void MCMF::print()
108 {
109     for(int i=head[n+2];i!=-1;i=edge[i].next)
110         if(edge[i].f==1&&edge[i].t!=n+4)
111             printf("%d ",edge[i].t-1);
112     printf("
");
113     for(int i=head[n+3];i!=-1;i=edge[i].next)
114         if(edge[i].f==1&&edge[i].t!=n+4)
115             printf("%d ",edge[i].t-1);
116 }
117 int a,b;
118 int main()
119 {
120     int s,t,c;
121     scanf("%d%d%d",&n,&a,&b);
122     MCMF *temp=new MCMF(1,n+4);
123     for(int i=1;i<=n;i++)
124         temp->insert(1,i+1,1,0);
125     for(int i=1;i<=n;i++)
126     {
127         scanf("%d",&m);
128         temp->insert(i+1,n+2,1,-m);
129     }
130     for(int i=1;i<=n;i++)
131     {
132         scanf("%d",&m);
133         temp->insert(i+1,n+3,1,-m);
134     }
135     temp->insert(n+2,n+4,a,0);
136     temp->insert(n+3,n+4,b,0);
137     temp->mcmf();
138     temp->print();
139     return 0;
140 }
原文地址:https://www.cnblogs.com/lthb/p/6035511.html