电脑公司生产电脑有N个机器,每个机器单位时间产量为Qi。
电脑由P个部件组成,每个机器工作时只能把有某些部件的半成品电脑(或什么都没有的空电脑)变成有另一些部件的半成品电脑或完整电脑(也可能移除某些部件)。求电脑公司的单位时间最大产量,以及哪些机器有协作关系,即一台机器把它的产品交给哪些机器加工。
Sample input
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 output
25 2
1 3 15
2 3 10
输入:电脑由3个部件组成,共有4台机器,1号机器产量15, 能给空电脑加上2号部件,2号 机器能给空电脑加上2号部件和3号部件, 3号机器能把有1个2号部件和3号部件有无均可的电脑变成成品(每种部件各有一个)
输出:单位时间最大产量25,有两台机器有协作关系,
1号机器单位时间内要将15个电脑给3号机器加工
2号机器单位时间内要将10个电脑给3号机器加工
数据规模很小,用EdmondsKarp就可以了。主要题目不仅要求最大流的值还要输出有流流过的边。
仔细想一想,这题不用拆点!
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> using namespace std; typedef long long LL; const int maxn = 60; const int inf = 0x7fffffff; struct Edge { int from,to,cap,flow; Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f) {} }; struct EdmondsKarp { int n,m; vector<Edge> edges; vector<int> G[maxn]; int p[maxn]; int a[maxn]; void init(int n) { this->n=n; for(int i=0; i<n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap) { edges.push_back(Edge(from,to,cap,0)); edges.push_back(Edge(to,from,0,0)); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } int Maxflow(int s,int t) { int flow=0; while(true) { memset(a,0,sizeof(a)); queue<int> Q; Q.push(s); a[s]=inf; while(!Q.empty()) { int x=Q.front(); Q.pop(); for(int i=0; i<G[x].size(); i++) { Edge &e=edges[G[x][i]]; if(!a[e.to]&&e.cap>e.flow) { a[e.to]=min(a[x],e.cap-e.flow); p[e.to]=G[x][i]; Q.push(e.to); if(e.to==t) break; } } if(a[t])break; } if(!a[t])break; for(int u=t; u!=s; u=edges[p[u]].from) { edges[p[u]].flow+=a[t]; edges[p[u]^1].flow-=a[t]; } flow+=a[t]; } return flow; } }; EdmondsKarp solver; int P, N; int w[maxn], in[maxn][12], out[maxn][12]; int print[maxn][5], cnt; int main() { int i, j; bool flag; while(~scanf("%d%d", &P, &N)) { int s = 0, t = N+1; solver.init(N+2); for(int i=1; i<=N; ++i) { scanf("%d", &w[i]); flag = true; for(j=0; j<P; ++j) { scanf("%d", &in[i][j]); if(in[i][j]==1) flag = false; } if(flag) solver.AddEdge(s, i, w[i]); flag = true; for(j=0; j<P; ++j) { scanf("%d", &out[i][j]); if(out[i][j]!=1) flag = false; } if(flag) solver.AddEdge(i, t, w[i]); } for(i=1; i<=N; ++i) { for(j=1; j<=N; ++j) { if(i==j) continue; flag = true; for(int k=0; k<P; ++k) if(out[i][k] + in[j][k] == 1) { flag = false; break; } if(flag) solver.AddEdge(i, j, min(w[i], w[j])); } } printf("%d ", solver.Maxflow(s, t)); cnt = 0; for(i=1; i<=N; ++i) for(j=0; j<solver.G[i].size(); ++j) { Edge &e = solver.edges[solver.G[i][j]]; if(e.flow>0 && e.to != t && e.from != s) { print[cnt][0] = e.from; print[cnt][1] = e.to; print[cnt++][2] = e.flow; } } printf("%d\n", cnt); for(i=0; i<cnt; ++i) printf("%d %d %d\n", print[i][0],print[i][1],print[i][2]); } return 0; }