poj 3436 -- ACM Computer Factory

ACM Computer Factory
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 5244   Accepted: 1796   Special Judge

Description

As you know, all the computers used for ACM contests must be identical, so the participants compete on equal terms. That is why all these computers are historically produced at the same factory.

Every ACM computer consists of P parts. When all these parts are present, the computer is ready and can be shipped to one of the numerous ACM contests.

Computer manufacturing is fully automated by using N various machines. Each machine removes some parts from a half-finished computer and adds some new parts (removing of parts is sometimes necessary as the parts cannot be added to a computer in arbitrary order). Each machine is described by its performance (measured in computers per hour), input and output specification.

Input specification describes which parts must be present in a half-finished computer for the machine to be able to operate on it. The specification is a set of P numbers 0, 1 or 2 (one number for each part), where 0 means that corresponding part must not be present, 1 — the part is required, 2 — presence of the part doesn't matter.

Output specification describes the result of the operation, and is a set of P numbers 0 or 1, where 0 means that the part is absent, 1 — the part is present.

The machines are connected by very fast production lines so that delivery time is negligibly small compared to production time.

After many years of operation the overall performance of the ACM Computer Factory became insufficient for satisfying the growing contest needs. That is why ACM directorate decided to upgrade the factory.

As different machines were installed in different time periods, they were often not optimally connected to the existing factory machines. It was noted that the easiest way to upgrade the factory is to rearrange production lines. ACM directorate decided to entrust you with solving this problem.

Input

Input file contains integers P N, then N descriptions of the machines. The description of ith machine is represented as by 2 P + 1 integers Qi Si,1 Si,2...Si,P Di,1 Di,2...Di,P, where Qi specifies performance, Si,j — input specification for part j, Di,k — output specification for part k.

Constraints

1 ≤ P ≤ 10, 1 ≤ N ≤ 50, 1 ≤ Qi ≤ 10000

Output

Output the maximum possible overall performance, then M — number of connections that must be made, then M descriptions of the connections. Each connection between machines A and B must be described by three positive numbers A B W, where W is the number of computers delivered from A to B per hour.

If several solutions exist, output any of them.

Sample Input

Sample input 1
3 4
15  0 0 0  0 1 0
10  0 0 0  0 1 1
30  0 1 2  1 1 1
3   0 2 1  1 1 1
Sample input 2
3 5
5   0 0 0  0 1 0
100 0 1 0  1 0 1
3   0 1 0  1 1 0
1   1 0 1  1 1 0
300 1 1 2  1 1 1
Sample input 3
2 2
100  0 0  1 0
200  0 1  1 1

Sample Output

Sample output 1
25 2
1 3 15
2 3 10
Sample output 2
4 5
1 3 3
3 5 3
1 2 1
2 4 1
4 5 1
Sample output 3
0 0

Hint

Bold texts appearing in the sample sections are informative and do not form part of the actual data.
 
思路: 添加一个超级源点与超级汇点。将P个机器看作P个点,每个点有 条件 和 结果。 如果条件中全为0,或者全为2,
或者只有0和2,那这个点与超级源点相连,这条边的容量为这个点的流量。如果结果中全为1,那么将这个点与超级汇点相连。
容量为这个点的流量。 然后判断每个点的结果与其他p-1个点的条件是否能达到要求,如果达到要求,将这两个点相连,容量为
两个点的最小流量,所谓的要求,即:如果有个点p3的条件为0 1 2 ,p4的结果为1 1 0,则p4不能与p3相连,因为p3的条件为:
1部件不需要,2部件需要,3部件无所谓。而p4的结果是1生产完毕,2生产完毕。3没有。与p3条件冲突。故不能连此边。通过总结
可以发现只要把条件与结果中相应部件相加,看是否等于1就能判断这两个点能不能建边。
建完图之后,就可以用dinic求最大流了。
其中可以通过反向边来看是否有流量通过,也就是通过这个来输出边。
 
  1 /*======================================================================
  2  *           Author :   kevin
  3  *         Filename :   ACMComputerFactory.cpp
  4  *       Creat time :   2014-07-27 09:35
  5  *      Description :
  6 ========================================================================*/
  7 #include <iostream>
  8 #include <algorithm>
  9 #include <cstdio>
 10 #include <cstring>
 11 #include <queue>
 12 #include <cmath>
 13 #define clr(a,b) memset(a,b,sizeof(a))
 14 #define N 105
 15 #define M 105
 16 #define INF 0x7f7f7f7f
 17 using namespace std;
 18 int n,p,supers,supert;
 19 struct Edge{
 20     int from,to,cap,flow;
 21 };
 22 vector<Edge>edges;
 23 vector<int>G[M];
 24 bool vis[M];
 25 int d[M],cur[M],flow[M],g[M][N],node[M][3];
 26 bool BFS()
 27 {
 28     clr(vis,0);
 29     queue<int>Q;
 30     Q.push(supers);
 31     d[supers] = 0;
 32     vis[supers] = true;
 33     while(!Q.empty()){
 34         int x = Q.front(); Q.pop();
 35         int len = G[x].size();
 36         for(int i = 0; i < len; i++){
 37             Edge& e = edges[G[x][i]];
 38             if(!vis[e.to] && e.cap > e.flow){
 39                 vis[e.to] = 1;
 40                 d[e.to] = d[x] + 1;
 41                 Q.push(e.to);
 42             }
 43         }
 44     }
 45     return vis[supert];
 46 }
 47 int DFS(int x,int a)
 48 {
 49     if(x == supert || a == 0) return a;
 50     int flow = 0,f;
 51     int len = G[x].size();
 52     for(int& i = cur[x]; i < len; i++){
 53         Edge& e = edges[G[x][i]];
 54         if( d[x] + 1 == d[e.to] && (f = DFS(e.to,min(a,e.cap-e.flow))) > 0){
 55             e.flow += f;
 56             edges[G[x][i]^1].flow -= f;
 57             flow += f;
 58             a -= f;
 59             if(!a) break;
 60         }
 61     }
 62     return flow;
 63 }
 64 void AddEdge(int from,int to,int cap)
 65 {
 66     edges.push_back((Edge) {from,to,cap,0});
 67     edges.push_back((Edge) {to,from,0,0});
 68     int m = edges.size();
 69     G[from].push_back(m-2);
 70     G[to].push_back(m-1);
 71 }
 72 int Dinic(int s,int t)
 73 {
 74     int flow = 0;
 75     while(BFS()){
 76         clr(cur,0);
 77         flow += DFS(s,INF);
 78     }
 79     return flow;
 80 }
 81 int main(int argc,char *argv[])
 82 {
 83     while(scanf("%d%d",&n,&p)!=EOF){
 84         clr(d,0);
 85         clr(node,0);
 86         clr(g,0);
 87         supers = 0;
 88         supert = p+1;
 89         for(int i = 1; i <= p; i++){
 90             scanf("%d",&flow[i]);
 91             int flag = 0;
 92             for(int j = 0; j < n; j++){
 93                 scanf("%d",&g[i][j]);
 94                 if(g[i][j] == 1){
 95                     flag = 1;
 96                 }
 97             }
 98             if(!flag){
 99                 AddEdge(supers,i,flow[i]);
100             }
101             flag = 0;
102             for(int j = n; j < 2*n; j++){
103                 scanf("%d",&g[i][j]);
104                 if(g[i][j] == 0){
105                     flag = 1;
106                 }
107             }
108             if(!flag){
109                 AddEdge(i,supert,flow[i]);
110             }
111         }
112         for(int i = 1; i <= p; i++){
113             for(int j = 1; j <= p; j++){
114                 if(i == j) continue;
115                 int flag =0;
116                 for(int k = n; k < 2*n; k++){
117                     if(g[i][k] + g[j][k-n] == 1){
118                         flag = 1; break;
119                     }
120                 }
121                 if(!flag){
122                     AddEdge(i,j,min(flow[j],flow[i]));
123                 }
124             }
125         }
126         int ans = Dinic(supers,supert);
127         printf("%d ",ans);
128         int cnt = 0;
129         for(int i = 1; i <= p; i++){
130             int len = G[i].size();
131             for(int j = 0; j < len; j++){
132                 if(edges[G[i][j]^1].from == 0 || edges[G[i][j]^1].from == p+1 ||
133                     edges[G[i][j]^1].to == 0 || edges[G[i][j]^1].to == p+1) 
134                     continue;
135                 if(edges[G[i][j]^1].flow < 0){
136                     node[cnt][0] = edges[G[i][j]^1].to;
137                     node[cnt][1] = edges[G[i][j]^1].from;
138                     node[cnt][2] = -edges[G[i][j]^1].flow;
139                     cnt++;
140                 }
141             }
142         }
143         printf("%d\n",cnt);
144         for(int i = 0; i < cnt; i++){
145             printf("%d %d %d\n",node[i][0],node[i][1],node[i][2]);
146         }
147         edges.clear();
148         for(int i = 0; i < M; i++){
149             G[i].clear();
150         }
151     }
152     return 0;
153 }
View Code

 

posted @ 2014-07-27 17:49  ZeroCode_1337  阅读(150)  评论(0编辑  收藏  举报