POJ 3436 ACM Computer Factory
2013-08-13 10:12
507 查看
这题的题目内容读起来很复杂,我来简单解释一下:
为了追求ACM比赛的公平性,所有用作ACM比赛的电脑性能是一样的,而ACM董事会专门有一条生产线来生产这样的电脑,随着比赛规模的越来越大,生产线的生产能力不能满足需要,所以说ACM董事会想要重新建造一条生产线。
生产线是全自动化的,所以需要机器来组成生产线,给定有多少中种机器,标准ACM用电脑有多少部份,每种机器将什么样的ACM电脑半成品处理成什么样的电脑半成品(对于输入的电脑半成品,每部分有0,1,2三种状态:代表着 0、这部分必须没有我才能处理,1、这部分必须有我才能处理,2、这部分有没有我都能处理。对于输出的电脑半成品有0,1两种状态:代表着0,处理完后的电脑半成品里没有这部分,1、处理完的电脑半成品有这部分),每一个机器每小时可以处理Q个半成品(输入数据中的Qi)。
求组装好的成产线的最大工作效率(每小时最多生成多少成品,成品的定义就是所有部分的状态都是“1”),和每两个机器之间的流量。
因为是Special Judge,所以对边的输出顺序没有要求(好像Discuss里有的数据过不去也AC了,这是什么情况?)。
这是一个不定源点和汇点的最大流问题,因为我们不能控制输入数据中用多少个输入状态全是"0"的机器,也不知道有多少个输出状态全是“1”的机器,所以我们需要虚拟一个超级源点和超级汇点来解决他们。
然后根据特征建图,EK算法,最后处理输出……
下面是代码:
为了追求ACM比赛的公平性,所有用作ACM比赛的电脑性能是一样的,而ACM董事会专门有一条生产线来生产这样的电脑,随着比赛规模的越来越大,生产线的生产能力不能满足需要,所以说ACM董事会想要重新建造一条生产线。
生产线是全自动化的,所以需要机器来组成生产线,给定有多少中种机器,标准ACM用电脑有多少部份,每种机器将什么样的ACM电脑半成品处理成什么样的电脑半成品(对于输入的电脑半成品,每部分有0,1,2三种状态:代表着 0、这部分必须没有我才能处理,1、这部分必须有我才能处理,2、这部分有没有我都能处理。对于输出的电脑半成品有0,1两种状态:代表着0,处理完后的电脑半成品里没有这部分,1、处理完的电脑半成品有这部分),每一个机器每小时可以处理Q个半成品(输入数据中的Qi)。
求组装好的成产线的最大工作效率(每小时最多生成多少成品,成品的定义就是所有部分的状态都是“1”),和每两个机器之间的流量。
因为是Special Judge,所以对边的输出顺序没有要求(好像Discuss里有的数据过不去也AC了,这是什么情况?)。
这是一个不定源点和汇点的最大流问题,因为我们不能控制输入数据中用多少个输入状态全是"0"的机器,也不知道有多少个输出状态全是“1”的机器,所以我们需要虚拟一个超级源点和超级汇点来解决他们。
然后根据特征建图,EK算法,最后处理输出……
下面是代码:
#include <stdio.h> #include <string.h> #include <queue> using namespace std; struct node { int in[12],out[12],ro; }machine[55]; const int inf = 1<<30; const int M =55; int map1[M][M],pre[M],vis[M],n; int min(int a,int b) { return a>b?b:a; } int EK() { int i,ans=0,now,min1; queue <int> q; while(1) //每循环一次找一次增广路 { memset(pre,-1,sizeof(pre)); memset(vis,0,sizeof(vis)); while(!q.empty()) { q.pop(); } q.push(0); vis[0]=1; while(!q.empty()) { now=q.front(); q.pop(); if(now==n+1) //已经搜索到超级汇点 跳出循环 { break; } for(i=0;i<=n+1;i++) { if(!vis[i]&&map1[now][i]>0)//如果节点i没被搜索过且节点now到节点i残余流量大于0 { pre[i]=now; //记录i的前驱节点是now vis[i]=1; //标记i点已经被访问过 q.push(i); //把i点放入队列进行下一次BFS } } } if(!vis[n+1]) { break; //如果BFS完毕没有搜到到节点n+1的增广路,就已经找到最大流 跳出 } min1=inf; for(i=n+1;i!=0;i=pre[i]) { if(map1[pre[i]][i]<min1) //寻找整个增广路上的残余流量的最小值,此为整个增广路的流量 { min1=map1[pre[i]][i]; } } ans+=min1; for(i=n+1;i!=0;i=pre[i]) { map1[pre[i]][i]-=min1;//残余流量减少 map1[i][pre[i]]+=min1;//已使用流量增加 } } return ans; } int main() { int p,backup[M][M],flat,an,i,j,k; while(scanf("%d%d",&p,&n)!=EOF) { int cut=0,ji[M][3]; for(i=1;i<=n;i++)//输入部分 { scanf("%d",&machine[i].ro); for(j=0;j<p;j++) { scanf("%d",&machine[i].in[j } for(j=0;j<p;j++) { scanf("%d",&machine[i].out[j]); } } memset(map1,0,sizeof(map1)); for(i=1;i<=n;i++) { int fs=1,ft=1; for(j=0;j<p;j++) { if(machine[i].in[j]==1) //判断其是能否和超级源点相连 { fs=0; } if(machine[i].out[j]==0) //判断其能否和超级汇点相连 { ft=0; } } if(fs) { map1[0][i]=machine[i].ro; } if(ft) { map1[i][n+1]=machine[i].ro; } for(j=1;j<=n;j++)//判断其能否和其他点相连 { if(i!=j) { flat=1; for(k=0;k<p;k++) { if(machine[i].out[k]+machine[j].in[k]==1) { flat=0; break; } } if(flat) { map1[i][j]=min(machine[i].ro,machine[j].ro); } } } } memcpy(backup,map1,sizeof(map1)); //做一个数据备份用来最后的时候比较用 an=EK(); for(i=1;i<=n;i++) //注意范围 超级源点和超级汇点是我们自己虚拟出来的,其实并不存在 { for(j=1;j<=n;j++) { if(backup[i][j]>map1[i][j]) { ji[cut][0]=i; ji[cut][1]=j; ji[cut][2]=backup[i][j]-map1[i][j]; cut++; } } } printf("%d %d\n",an,cut);//输出 for(i=0;i<cut;i++) { printf("%d %d %d\n",ji[i][0],ji[i][1],ji[i][2]); } } return 0; }
相关文章推荐
- POJ 3436 ACM Computer Factory
- POJ 3436:ACM Computer Factory
- 【最大流 && 输出路径】POJ - 3436 ACM Computer Factory
- POJ 3436 ACM Computer Factory 最大流输出路径
- poj 3436 ACM Computer Factory (最大流 拆点建图 找路径)@
- poj3436——ACM Computer Factory
- POJ 3436 ACM Computer Factory(最大流+路径输出)
- POJ 3436 ACM Computer Factory(Dinic)
- ACM Computer Factory(POJ--3436
- poj 3436 ACM Computer Factory
- ACM Computer Factory poj 3436 增广流
- POJ 3436 ACM Computer Factory
- A - ACM Computer Factory - poj 3436(最大流)
- poj 3436 ACM Computer Factory
- POJ 3436 ACM Computer Factory
- POJ-3436 ACM Computer Factory 最大流
- POJ 3436 ACM Computer Factory
- POJ-3436 ACM Computer Factory (最大流[Ford-Fulkerson])
- POJ 3436 ACM Computer Factory 最大流
- POJ 3436 ACM Computer Factory (拆点+最大流)