poj 3436 ACM Computer Factory
题意:...
解法:求最大流并给出一种流量分配方案.
建图过程,每个机器有入口和出口,所以要拆点.
如果不拆点的话,下面的样例可以cha掉这个解法
2 4
10 0 0 0 1
10 0 0 0 0
10 0 1 1 1
10 0 1 1 1
至于输出一种可行方案,我们可以想一下dinic算法的执行流程,每次增广的过程都发生在dfs的时候,所以在回退增广的时候我们可以记录下这条边是否被增广...
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define N 110 6 #define M 10010 7 using namespace std; 8 const int inf=1<<30; 9 struct Edge{ 10 int u,v,c,next,used; 11 }edge[M]; 12 int head[N],dis[N],queue[M],stack[M]; 13 int v[N],in[N][N],out[N][N],o[N]; 14 int S[N],T[N],source,sink; 15 int cnt,p,n; 16 void init(){ 17 cnt=0; 18 memset(head,-1,sizeof(head)); 19 for(int i=1;i<=p;i++){ 20 S[i]=0; 21 T[i]=1; 22 } 23 } 24 void addedge(int u,int v,int c){ 25 edge[cnt].u=u;edge[cnt].v=v;edge[cnt].c=c; 26 edge[cnt].used=0; 27 edge[cnt].next=head[u];head[u]=cnt++; 28 } 29 int dinic(int s,int t){ 30 int ans=0; 31 while(1){ 32 int l,r,now,u,v,top; 33 memset(dis,-1,sizeof(dis)); 34 l=r=0; 35 queue[r++]=s; 36 dis[s]=0; 37 while(l<r){ 38 u=queue[l++]; 39 for(int k=head[u];k!=-1;k=edge[k].next){ 40 u=edge[k].u; 41 v=edge[k].v; 42 if(edge[k].c>0&&dis[v]==-1){ 43 dis[v]=dis[u]+1; 44 queue[r++]=v; 45 if(v==t){ 46 l=r; 47 break; 48 } 49 } 50 } 51 } 52 if(dis[t]==-1)break; 53 now=s; 54 top=0; 55 while(1){ 56 if(now!=t){ 57 int k; 58 for(k=head[now];k!=-1;k=edge[k].next){ 59 if(edge[k].c>0&&dis[edge[k].v]==dis[edge[k].u]+1)break; 60 } 61 if(k!=-1){ 62 stack[top++]=k; 63 now=edge[k].v; 64 } 65 else{ 66 if(top==0)break; 67 dis[edge[stack[--top]].v]=-1; 68 now=edge[stack[top]].u; 69 } 70 } 71 else{ 72 int flow=inf,w; 73 for(int i=0;i<top;i++){ 74 if(flow>edge[stack[i]].c){ 75 flow=edge[stack[i]].c; 76 w=i; 77 } 78 } 79 ans+=flow; 80 for(int i=0;i<top;i++){ 81 edge[stack[i]].c-=flow; 82 edge[stack[i]^1].c+=flow; 83 edge[stack[i]^1].used=1; 84 } 85 now=edge[stack[w]].u; 86 top=w; 87 } 88 } 89 } 90 return ans; 91 } 92 93 bool ok(int *a,int *b){ 94 for(int i=1;i<=p;i++) 95 if(a[i]+b[i]==1)return 0; 96 return 1; 97 } 98 int abs(int a,int b){ 99 return a>b?a-b:b-a; 100 } 101 int main(){ 102 // freopen("in.in","r",stdin); 103 while(~scanf("%d%d",&p,&n)){ 104 init(); 105 for(int i=1;i<=n;i++){ 106 scanf("%d",&v[i]); 107 for(int j=1;j<=p;j++) 108 scanf("%d",&in[i][j]); 109 for(int j=1;j<=p;j++) 110 scanf("%d",&out[i][j]); 111 } 112 source=0,sink=2*n+1; 113 for(int i=1;i<=n;i++){ 114 addedge(i,i+n,v[i]); 115 addedge(i+n,i,0); 116 } 117 for(int i=1;i<=n;i++){ 118 if(ok(S,in[i])){ 119 addedge(source,i,inf); 120 addedge(i,source,0); 121 } 122 if(ok(T,out[i])){ 123 addedge(i+n,sink,inf); 124 addedge(sink,i+n,0); 125 } 126 } 127 for(int i=1;i<=n;i++){ 128 for(int j=1;j<=n;j++){ 129 if(i==j)continue; 130 if(ok(out[i],in[j])){ 131 addedge(i+n,j,inf); 132 addedge(j,i+n,0); 133 } 134 } 135 } 136 int ans=dinic(source,sink); 137 int num=0; 138 for(int i=0;i<cnt;i++) 139 if(edge[i].used){ 140 if(edge[i].u==source||edge[i].v==source)continue; 141 if(edge[i].u==sink||edge[i].v==sink)continue; 142 if(abs(edge[i].u,edge[i].v)==n)continue; 143 o[++num]=i; 144 } 145 printf("%d %d\n",ans,num); 146 for(int i=1;i<=num;i++) 147 printf("%d %d %d\n",edge[o[i]].v>n?edge[o[i]].v-n:edge[o[i]].v,edge[o[i]].u>n?edge[o[i]].u-n:edge[o[i]].u,edge[o[i]].c); 148 } 149 return 0; 150 }