标签:过程 this min size push 表示 main 最小费用最大流 无法
题意:有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("\n"); 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 }
标签:过程 this min size push 表示 main 最小费用最大流 无法
原文地址:http://www.cnblogs.com/lthb/p/6035511.html