题意:有n个机器加工计算机,有p个计算机零件,接下来输出n个机器加工计算机情况,2*p+1个数据,第一个是每小时最多生产计算机台数,接下来p个数是,可以从p个零件状态的计算机生产到后面p个零件状态的计算机。问最多一小时生产多少计算机。
当然这里零件状态是这样定义的,0表示没有,1表示必须要,2表示可有可无(所以2可以无视)
思路:
当然是从零件全是0的计算机开始了。然而你忘了有2也是可以的,只要零件非1就行。(一个坑点)
会想到有很多可以加工全非1的机器,和加工到全1的机器,那么就是一个多源点,多汇点的网络流,就要用一个超级源点,超级汇点。
超级源点连接可以从零件全非1开始加工的机器,而可以加工到全为1的机器连接超级汇点(第一步)
那么下一步就是连接机器,看是否加工的半成品是否可以给下一个机器加工。只要每个零件对应不能同时一个0,一个1,即可。(第二步)
接下来就是求网络流最大流量了,这里用dinic算法模板就行。(第三步)
最后只要计算有流量的路径并输出即可。(最后一步)
最后想复杂了,以为要输出每条增广路径,最后wa了几发。。。
代码:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<queue> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; struct node{ int c,f; }mp[100][100]; int sx,ex,n,m,cnt; int g[100][100]; int step[100],ans,li,outline[100][5]; //li记录流量路径条数,outline记录路径情况 bool bfs()//dinic--求层次网络 { memset(step,0,sizeof(step)); step[sx]=1; queue<int> q; q.push(sx); while(!q.empty()) { int p=q.front(); q.pop(); for(int i=0;i<=m+1;i++) { if(!step[i]&&mp[p][i].c-mp[p][i].f) { step[i]=step[p]+1; q.push(i); } } } return step[ex]!=0; } int dinic(int pos,int flow)//求出层次网络中所有增广路径流量 { int f=flow; if(pos==ex) return flow; for(int i=0;i<=m+1;i++) { if(mp[pos][i].c-mp[pos][i].f&&step[pos]+1==step[i]) { int a=mp[pos][i].c-mp[pos][i].f; int t=dinic(i,min(a,flow)); mp[pos][i].f+=t; mp[i][pos].f-=t; flow-=t; } } return f-flow; } void solve()//最大流 { while(bfs()) { ans+=dinic(sx,inf); } return ; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { memset(mp,0,sizeof(mp)); sx=0,ex=m+1;//起点sx,终点ex ans=0,li=0; for(int i=1;i<=m;i++) for(int j=0;j<=2*n;j++) scanf("%d",&g[i][j]); for(int i=1;i<=m;i++)//判断是否可以连接超级源点或超级汇点 { int flag1=0,flag2=0; for(int j=1;j<=n;j++) { if(g[i][j]==1) flag1=1; if(g[i][j+n]==0) flag2=1; } if(!flag1)//连接超级源点 mp[sx][i].c=g[i][0]; if(!flag2)//连接超级汇点 mp[i][ex].c=g[i][0]; } for(int i=1;i<=m;i++)//判断是否可以两两工厂相连 { for(int j=1;j<=m;j++) { if(i==j) continue; int flag=0; for(int k=1;k<=n;k++) { if(g[i][k+n]+g[j][k]==1) { flag=1; break; } } if(flag) continue; mp[i][j].c=min(g[i][0],g[j][0]); } } solve();//求最大流 for(int i=1;i<=m;i++)//判断路是否有流量 { for(int j=1;j<=m;j++) { if(mp[i][j].f>0) { li++; outline[li][1]=i; outline[li][2]=j; outline[li][3]=mp[i][j].f; } } } cout<<ans<<' '<<li<<endl; for(int i=1;i<=li;i++) { cout<<outline[i][1]<<' '<<outline[i][2]<<' '<<outline[i][3]<<endl; } } return 0; }