POJ 3436:拆点最大流

来源:互联网 发布:北大燕京学堂知乎 编辑:程序博客网 时间:2024/05/18 02:57

题意:一个电脑有P个部件组成,刚开始所有电脑都是空壳子,当一个电脑具备了所有的N个部件则认为这个电脑早好了。现在有一些机器专门加工电脑,每个机器可以加工某一些特性状态原型机,比如必须具备1部件,必须没有3部件,2部件有没有都行,然后这些原型机经过这个机器的加工,就会变成一种特定状态,比如具备123部件,没有45部件。每个机器每小时可以加工qi个原型机。

求出每小时最多生产多少个成品机。以及流水线的运作情况。


题解:题意特别绕。。。。但是题解是很显然的网络流。对于每个机器,拆成一个入点和出点,入点->出点链接一个容量qi的边。然后二重枚举机器,如果第i个机器的输出可以做得第j个机器的输入,那么就链接i的出点->j的入点,容量INF。然后再开一个超级源,如果裸机可以作为i点的输入,就链接源->i的入点,容量INF。如果第i个机器产出成品机,那就链接i的出点->汇,容量INF。


这里机器的每小时加工数量在入点-出点的边限制住了。


很裸的网络流。。。和网络流基本的油管运输问题基本一摸一样。

Code:

#include<stdio.h>#include<cstring> #include<queue>using namespace std;const int maxn = 55;const int maxp = 15;const int INF = 0x3f3f3f3f;int in[maxn*2][maxp],out[maxn][maxp],q[maxn];int tot,first[maxn],nxt[maxn*maxn],des[maxn*maxn],flow[maxn*maxn];int dep[maxn];int ss,tt;int p,n;inline void addEdge(int x,int y,int z){tot++;des[tot] =y;flow[tot] =z;nxt[tot] = first[x];first[x] = tot;tot++;des[tot] =x;flow[tot] =0;nxt[tot] = first[y];first[y] = tot;}void init(){ss=1;tt=2*n+2;tot =-1;}void input(){//scanf("%d%d",&p,&n);for (int i=2;i<=n+1;i++){scanf("%d",q+i);for (int j=0;j<p;j++){scanf("%d",&in[i][j]);}for (int j=0;j<p;j++){scanf("%d",&out[i][j]);}}}void build (){memset(first,-1,sizeof first);for (int i=2;i<=n+1;i++){addEdge(i,i+n,q[i]);bool flag =true;for (int j=0;j<p;j++){if (in[i][j]==1){flag = false;break;}}if (flag){addEdge(ss,i,INF);}flag = true;for (int j=0;j<p;j++){if (out[i][j]!=1){flag = false;break;}}if (flag){addEdge(i+n,tt,INF);}}for (int i=2;i<=1+n;i++){for (int j=2;j<=1+n;j++){if (i==j)continue;bool flag = true;for (int k=0;k<p;k++){if (out[i][k]==in[j][k]||in[j][k]==2)continue;else{flag = false;break;}}if (flag){addEdge(i+n,j,INF);}}}}bool bfs(){//cout<<"bfs"<<endl;queue<int> Q;memset(dep,-1,sizeof dep);dep[ss]=0;Q.push(ss);while (!Q.empty()){int q = Q.front();Q.pop();for (int t = first[q];t!=-1;t=nxt[t]){int v = des[t];int c = flow[t];if (c&&dep[v]==-1){dep[v] = dep[q]+1;Q.push(v);}}}return dep[tt]!=-1;}int dfs(int node,int now){//cout<<"dfs"<<endl;if (node==tt)return now;int ret =0;for (int  t= first[node];t!=-1&&ret<now;t=nxt[t]){int v = des[t];int c = flow[t];if (dep[v]==dep[node]+1&&c){int x = min(c,now-ret);x = dfs(v,x);flow[t]-=x;flow[t^1]+=x;ret+=x;}}if (!ret)dep[node] =-1;return ret;}int max_flow(){int tot =0;while (bfs()){int del;while (del=dfs(ss,INF)){tot+=del;}}return tot;}void solve(){int ans =max_flow();vector<pair<pair<int,int>,int> >list;for (int i=2;i<=n+1;i++){for (int t = first[i];t!=-1;t = nxt[t]){int v = des[t];int c = flow[t];if (c&&v>n+1&&v!=2*n+2&&v!=i+n){//printf("%d %d %d\n",v-n-1,i-1,c);list.push_back(make_pair(make_pair(v-n-1,i-1),c));}}}printf("%d %d\n",ans,list.size());for (int i=0;i<list.size();i++){printf("%d %d %d\n",list[i].first.first,list[i].first.second,list[i].second);}}int main(){while (scanf("%d%d",&p,&n)!=EOF){init();input();build();solve();}return 0;}


原创粉丝点击