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 }

 

 

 

posted @ 2012-11-24 16:42  silver__bullet  阅读(149)  评论(0编辑  收藏  举报