题意:不想描述了。。直接从这个博客抄了: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 ",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 ",ans); 105 for(int i = 0;i < ans;i++){ 106 printf("%d %d %d ",res[i][0],res[i][1],res[i][2]); 107 } 108 } 109 return 0; 110 }