POJ 3436 ACM Computer Factory 【网络流】【北大ACM/ICPC竞赛训练】

我ac掉网络流的第一题!

先总结一下网络流的一些算法吧,首先是Ford-Fulkerson算法,这个算法是保证了众多网络流算法的【正确性】,其他算法也是基于其【优化】得到的。Ford的算法在于引入“反向边”的概念,反向边就是反悔边,代表你给修正以前走了的边一个机会。为什么反向边是对的呢,凭空加进来一条边真的大丈夫吗,关于这个有相关正确性的证明,我也说不清楚只能直觉上去理解。

之后是Edmonds-Karp即最短增广路算法,顾名思义,每次都找到达汇点边数最少的增广路,由此避免一些特定的消耗时间的情况。

然后是我现在用的Dinic算法,它的优化在于之前的两次算法都是每次找一条增广路,但实际上我们可以一次找【多条增广路】,所以手工写deque加回溯又可以进一步缩小时间复杂度。

一道网络流的题出的好不好,在于一眼能不能让选手看出是网络流模型。这道题我觉得出的蛮好的,把每个machine的input和output当作点去建边,就可以了。(input编号就是机器编号,output编号是其input编号加n,这样就可以把每个点标示出来了,其中一个input到另一个input或output到另一个output没有意义,所以就是0)

  1 #include<iostream>
  2 #include<cmath>
  3 #include<vector>
  4 #include<queue>
  5 #include<deque>
  6 #include<cstring>
  7 #define INF 1000000000
  8 using namespace std;
  9
 10 int n,p;
 11 struct node{
 12     int in[12],out[12];
 13     int flow;
 14     node(int f1=0): flow(f1) {
 15         memset(in,0,sizeof(in));
 16         memset(out,0,sizeof(out));
 17     }
 18 }machine[110];
 19 int G[105][105],G2[105][105],layer[110];//G2是残余网络
 20 struct node1{
 21     int from,to,vol;
 22     node1(int i1=0,int j1=0,int v1=0): from(i1),to(j1),vol(v1) {}
 23 };
 24 vector<node1> ans;
 25
 26 bool ok(int a,int b){//从a的output输送到b的input
 27     for(int i=1;i<=p;i++){
 28         if( machine[a].out[i]==machine[b].in[i] || machine[b].in[i]==2 ) continue;
 29         return false;
 30     }
 31     return true;
 32 }
 33
 34 bool check0(int a){//源点到a机器的input可不可以
 35     for(int i=1;i<=p;i++){
 36         if( machine[a].in[i]==1 ) return false;
 37     }
 38     return true;
 39 }
 40
 41 bool check1(int a){//a机器的output到汇点可不可以
 42     for(int i=1;i<=p;i++){
 43         if( machine[a].out[i]!=1 ) return false;
 44     }
 45     return true;
 46 }
 47
 48 int vis[1005];
 49 bool count_floor(){
 50     memset(layer,-1,sizeof(layer));
 51     layer[0]=0;
 52     queue<int> q;//int记录现在在的节点位置
 53     q.push(0);
 54     while(!q.empty()){
 55         int u = q.front(); q.pop();
 56         if(u==2*n+1) return true;
 57         for(int i=0;i<=2*n+1;i++){//枚举所有节点
 58             if( G2[u][i]>0 && layer[i]==-1 ){
 59                 layer[i]=layer[u]+1;
 60                 q.push(i);
 61             }
 62         }
 63     }
 64     return false;//搜不到汇点了
 65 }
 66
 67 int dinic(){
 68     //源点是0
 69     int maxflow=0;
 70     deque<int> s;//int记录目前dfs到的节点
 71     while( count_floor() ){
 72         s.push_back(0);
 73         memset(vis,0,sizeof(vis)); vis[0]=1;
 74         while(!s.empty()){
 75             int u = s.back();//先不急着pop_back掉
 76             if( u==2*n+1 ){//找到一条增广路径
 77                 int minflow=INF,min_u;
 78                 for(int i=1;i<s.size();i++){
 79                     int u1=s[i-1],v1=s[i];
 80                     if( G2[u1][v1]<minflow ){ minflow=G2[u1][v1]; min_u=u1; }
 81                 }//找到一路上最细的管道
 82                 maxflow+=minflow;
 83                 for(int i=1;i<s.size();i++){
 84                     int u1=s[i-1],v1=s[i];
 85                     G2[u1][v1]-=minflow;//减掉原边
 86                     G2[v1][u1]+=minflow;//加上反向边
 87                 }
 88                 while(!s.empty() && s.back()!=min_u) {
 89                     vis[ s.back() ] = 0;
 90                     s.pop_back();
 91                 }
 92             }//都结束了,自动回溯到最上面的点u使得u以上的树边flow不为0
 93             else{//到了一个点,向下dfs
 94                 int i;
 95                 for(i=0;i<=2*n+1;i++){
 96                     if( G2[u][i]>0 && layer[i]==layer[u]+1 && !vis[i] ){//每一次只往下一层走
 97                         vis[i]=1;
 98                         s.push_back(i);
 99                         break;
100                     }
101                 }
102                 if(i==2*n+2) s.pop_back();
103             }
104         }
105     }
106
107     return maxflow;
108 }
109
110
111 int main(){
112
113     while(scanf("%d%d",&p,&n)!=EOF){
114         for(int i=1;i<=n;i++){
115             cin>>machine[i].flow;
116             for(int j=1;j<=p;j++) cin>>machine[i].in[j];
117             for(int j=1;j<=p;j++) cin>>machine[i].out[j];
118         }
119
120         //开始建图
121         for(int i=1;i<=n;i++) G2[i][i+n]=G[i][i+n]=machine[i].flow;//从n的input到n的output
122         //output代表的节点是机器的编号+n
123         //源点是0,汇点是2n+1
124         for(int i=1;i<=n;i++){
125             if( check0(i) ) G2[0][i]=G[0][i]=INF;
126             if( check1(i) ) G2[i+n][2*n+1]=G[i+n][2*n+1]=INF;
127         }
128
129         //建每个机器的output能不能到其他机器的input
130         for(int i=1;i<=n;i++){
131             for(int j=1;j<=n;j++){
132                 if(i==j) continue;
133                 if( ok(i,j) ) G2[i+n][j]=G[i+n][j]=INF;
134             }
135         }
136
137         cout<<dinic()<<" ";
138         for(int i=1;i<=n;i++){
139             for(int j=1;j<=n;j++){
140                 if(i==j) continue;
141                 if( ok(i,j) && G[i+n][j]-G2[i+n][j]>0 ) ans.push_back( node1(i,j,G[i+n][j]-G2[i+n][j]) );
142             }
143         }
144         cout<<ans.size()<<endl;
145         for(int i=0;i<ans.size();i++) cout<<ans[i].from<<" "<<ans[i].to<<" "<<ans[i].vol<<endl;
146         ans.clear();
147     }
148
149     return 0;
150 }

原文地址:https://www.cnblogs.com/ZhenghangHu/p/9410691.html

时间: 2024-10-08 15:16:10

POJ 3436 ACM Computer Factory 【网络流】【北大ACM/ICPC竞赛训练】的相关文章

POJ - 3436 ACM Computer Factory 网络流

POJ-3436:http://poj.org/problem?id=3436 题意 组配计算机,每个机器的能力为x,只能处理一定条件的计算机,能输出特定的计算机配置.进去的要求有1,进来的计算机这个位子就要求为1,进去的要求有0,进来的计算机这个位子就要求为0. 思路 因为点上有容量限制,所以把每个点拆掉,连一条容量为这个机器的能力的边.源点向要求为0的机器连容量inf的边,把能完全组装好计算机的机器连向汇点.中间把符合条件的机器间连边,容量为inf: #include <algorithm>

POJ 3436 ACM Computer Factory(网络最大流)

http://poj.org/problem?id=3436 ACM Computer Factory Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 5286   Accepted: 1813   Special Judge Description As you know, all the computers used for ACM contests must be identical, so the particip

Poj 3436 ACM Computer Factory (最大流)

题目链接: Poj 3436 ACM Computer Factory 题目描述: n个工厂,每个工厂能把电脑s态转化为d态,每个电脑有p个部件,问整个工厂系统在每个小时内最多能加工多少台电脑? 解题思路: 因为需要输出流水线要经过的工厂路径,如果要用电脑状态当做节点的话,就GG了.所以建图的时候要把工厂当做节点.对于节点i,能生产si电脑的节点可以进入节点i,能转化ei电脑的节点可以由i节点进入.要注意对于每一个节点要进行拆点,防止流量发生错误. 1 #include <queue> 2 #

POJ 3436 ACM Computer Factory (最大流 + 输出路径)

POJ 3436 ACM Computer Factory 链接:http://poj.org/problem?id=3436 题意:每台电脑有P部分,可以通过不同的机器来进行加工.有N台机器,每台机器用2 P +1 个整数来描述:Qi  Si,1  Si,2 ...  Si,p  Di,1  Di,2. ..  Di,p,其中Qi 指定了机器的性能,表示每小时加工的电脑数量.Si,j 为第j 部分的输入规格,0表示该部分不能被加工过,1表示该部分必须被加工过,2表示都可以.Di,k 为第k 部

18.11.23 POJ 3436 ACM Computer Factory(dinic)

描述 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 the

POJ-3436 ACM Computer Factory(网络流EK)

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

poj3436 ACM Computer Factory, 最大流,输出路径

POJ 3436 ACM Computer Factory 电脑公司生产电脑有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

POJ-3436 ACM Computer Factory (最大流[Ford-Fulkerson])

ACM Computer Factory http://poj.org/problem?id=3436 Time Limit: 1000MS   Memory Limit: 65536K         Special Judge Description As you know, all the computers used for ACM contests must be identical, so the participants compete on equal terms. That i

POJ3436:ACM Computer Factory(最大流)

ACM Computer Factory Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9963   Accepted: 3738   Special Judge 题目链接:http://poj.org/problem?id=3436 Description: As you know, all the computers used for ACM contests must be identical, so the pa

解题报告 之 POJ3463 ACM Computer Factory

解题报告 之 POJ3463 ACM Computer Factory 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 A