POJ 3436 ACM Computer Factory

题意:不想描述了。。直接从这个博客抄了:http://www.cnblogs.com/rainydays/archive/2011/07/01/2095634.html

有一些机器用来组装电脑,每台机器对输入机器的电脑有要求,符合要求的电脑被送入机器后会输出一台规定配件情况的电脑。而且分别告知每台机器在单位时间内处理电脑的台数。将这些机器连成生产线,问单位时间内出产的具有所有配件的电脑最多有多少台。

其实就是个拆点的最大流,然后要求输出所有边的流量有变化的正向边。当然也可以不拆点做。WA了一次,题目有个小坑,就是如果所有输入都是2,那么它还是可以跟源点相连的。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 const int maxn = 60;
  6 const int maxm = 100000;
  7 const int INF = 1<<30;
  8 int u[maxm],v[maxm],next[maxm],w[maxm],p[maxm],res[maxm][3];
  9 int first[maxn],d[maxn],work[maxn],q[maxn];
 10 int e,S,T,P,N;
 11 int in[60][15],out[60][15],Q[60];
 12 
 13 void init(){
 14     e = 0;
 15     memset(first,-1,sizeof(first));
 16 }
 17 
 18 void add_edge(int a,int b,int c){
 19     //printf("add:%d to %d,cap = %d\n",a,b,c);
 20     u[e] = a;v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
 21     u[e] = b;v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
 22 }
 23 
 24 int bfs(){
 25     int rear = 0;
 26     memset(d,-1,sizeof(d));
 27     q[rear++] = S;d[S] = 0;
 28     for(int i = 0;i < rear;i++){
 29         for(int j = first[q[i]];j != -1;j = next[j])
 30             if(w[j] && d[v[j]] == -1){
 31                 d[v[j]] = d[q[i]] + 1;
 32                 q[rear++] = v[j];
 33                 if(v[j] == T)   return 1;
 34             }
 35     }
 36     return 0;
 37 }
 38 
 39 int dfs(int cur,int a){
 40     if(cur == T)    return a;
 41     for(int &i = work[cur];i != -1;i = next[i]){
 42         if(w[i] && d[v[i]] == d[cur] + 1)
 43             if(int t = dfs(v[i],min(a,w[i]))){
 44                 w[i] -= t;w[i^1] += t;
 45                 return t;
 46             }
 47     }
 48     return 0;
 49 }
 50 
 51 int dinic(){
 52     int ans = 0;
 53     while(bfs()){
 54         memcpy(work,first,sizeof(first));
 55         while(int t = dfs(S,INF))   ans += t;
 56     }
 57     return ans;
 58 }
 59 
 60 bool judge(int a,int b){
 61     for(int i = 1;i <= P;i++){
 62         if(out[a][i] == 0 && in[b][i] == 1) return false;
 63         if(out[a][i] == 1 && in[b][i] == 0) return false;
 64     }
 65     return true;
 66 }
 67 
 68 int main()
 69 {
 70     while(scanf("%d%d",&P,&N) == 2){
 71         init();
 72         S = 0,T = N+1;
 73         for(int i = 1;i <= N;i++){
 74             scanf("%d",&Q[i]);
 75             int tmp = 0;
 76             for(int j = 1;j <= P;j++){
 77                 scanf("%d",&in[i][j]);
 78                 tmp += in[i][j];
 79             }
 80             if(tmp == 0 || tmp == P*2)    add_edge(S,i,Q[i]);
 81             tmp = 0;
 82             for(int j = 1;j <= P;j++){
 83                 scanf("%d",&out[i][j]);
 84                 tmp += out[i][j];
 85             }
 86             if(tmp == P)    add_edge(i,T,Q[i]);
 87         }
 88         int cnt = 0;
 89         for(int i = 1;i <= N;i++){
 90             for(int j = 1;j <= N;j++){
 91                 if(i == j)  continue;
 92                 if(judge(i,j))  p[cnt++] = e,add_edge(i,j,min(Q[i],Q[j]));
 93             }
 94         }
 95         printf("%d",dinic());
 96         int ans = 0;
 97         for(int i = 0;i < cnt;i++){
 98             if(w[p[i]^1] != 0){
 99                 res[ans][0] = u[p[i]];
100                 res[ans][1] = v[p[i]];
101                 res[ans++][2] = w[p[i]^1];
102             }
103         }
104         printf(" %d\n",ans);
105         for(int i = 0;i < ans;i++){
106             printf("%d %d %d\n",res[i][0],res[i][1],res[i][2]);
107         }
108     }
109     return 0;
110 }
View Code

 

posted @ 2013-11-13 23:10  浙西贫农  阅读(163)  评论(0编辑  收藏  举报