题 意:有一个ACM工厂会生产一些电脑,在这个工厂里面有一些生产线,分别生产不同的零件,不过他们生产的电脑可能是一体机,所以只能一些零件加工后别的生 产线才可以继续加工,比如产品A在生产线1号加工后继续前往生产线2号继续加工,直到成为完全产品。输入 P 意思是这个电脑需要P个零件,N表示有N个生产线,每个生产线都有最大加工量,并且需要什么零件和输出的是什么零件,0表示没有这个零件,1表示有这个零 件,2表示有没有都可以。
样例说明:
3 4
1号: 15 0 0 0 --> 0 1 0
2号: 10 0 0 0--> 0 1 1
3号: 30 0 1 2 --> 1 1 1
4号: 3 0 2 1 --> 1 1 1
1号生产线需要0 0 0这样的零件(这样的零件也就是无限制零件,源点),它可以把零件加工成 0 1 0 这个样子,然后 3 号生产线可以接受这种零件,并且加工成 1 1 1 也就是成品,到这样也就加工成功了,因为1号生产线每次可以加工 15 个零件,所以1->3的加工量就是 15,同理 2->3的加工量是 10,所以结果是 25。
分析:很明显的网络流题目,感觉难点应该在题目阅读和建图上.....可以用0当做源点 N+1当做汇点,然后每两点都进行匹配一些,看看是否可以连接,路径的权值为出点的生产能力。
注意:因为每个生产线的生产能力有限,所以需要拆点,防止超出他的生产能力,比如下图如果不拆点结果就会使20,实际上是10
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <queue> using namespace std; const int oo=0x3f3f3f3f; struct node { int flow; int in[55]; int out[55]; }a[20]; int maps[111][111]; int x[10005];int y[10005],z[10005]; int oldmaps[111][111]; int layer[111]; int p,n; void init() { memset(maps,0,sizeof(maps)); memset(oldmaps,0,sizeof(oldmaps)); for(int i=1;i<=p;i++) { a[1].in[i]=0; a[1].out[i]=0; a[n+2].in[i]=1; a[n+2].out[i]=1; } a[1].flow=oo; a[n+2].flow=oo; } int can(int x,int y) { for(int i=1;i<=p;i++) { if(a[x].out[i]!=a[y].in[i]&&a[y].in[i]!=2) return 0; } return 1; } int bfs(int s,int End) { memset(layer,0,sizeof(layer)); queue<int>q; q.push(s); layer[s]=1; while(q.size()) { s=q.front(); q.pop(); if(s==End) { return 1; } for(int i=1;i<=End;i++) { if(maps[s][i]&&layer[i]==0) { layer[i]=layer[s]+1; q.push(i); } } } return 0; } int dfs(int s,int End,int maxflow) { if(s==End) return maxflow; int iflow=0; for(int i=1;i<=End;i++) { if(maps[s][i]>0&&layer[s]==layer[i]-1) { int flow=min(maxflow-iflow,maps[s][i]); flow=dfs(i,End,flow); maps[s][i]-=flow; maps[i][s]+=flow; iflow+=flow; if(maxflow==iflow) break; } } return iflow; } int Dinic() { int max_flow=0; while(bfs(1,n*2)) { max_flow+=dfs(1,n*2,oo); } return max_flow; } int main() { while(~scanf("%d%d",&p,&n)) { init(); for(int i=2; i<=n+1; i++) { scanf("%d",&a[i].flow); for(int j=1; j<=p; j++) { scanf("%d",&a[i].in[j]); } for(int j=1;j<=p;j++) { scanf("%d",&a[i].out[j]); } } n+=2; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) { oldmaps[i][j+n]=maps[i][j+n]=a[i].flow; } else { if(can(i,j)) oldmaps[i+n][j]=maps[i+n][j]=min(a[i].flow,a[j].flow); else oldmaps[i+n][j]=maps[i+n][j]=0; } } } int sum=Dinic(); int k=0; for(int i=2;i<n;i++) { for(int j=2;j<n;j++) { if(maps[i+n][j]<oldmaps[i+n][j]) { x[k]=i;y[k]=j; z[k]=oldmaps[i+n][j]-maps[i+n][j]; k++; } } } printf("%d %d ",sum,k); for(int i=0;i<k;i++) printf("%d %d %d ",x[i]-1,y[i]-1,z[i]); } return 0; } /* 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 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 2 2 100 0 0 1 0 200 0 1 1 1 */