您的位置:首页 > 其它

POJ 3436-ACM Computer Factory(最大流输出路径-Edmond-Karp算法)

2017-02-13 18:48 501 查看
ACM Computer Factory

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 7445 Accepted: 2664 Special Judge
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 ACM computer consists of P parts. When all these parts are present, the computer is ready and can be shipped to one of the numerous ACM contests.

Computer manufacturing is fully automated by using N various machines. Each machine removes some parts from a half-finished computer and adds some new parts (removing of parts is sometimes necessary as the parts cannot be added to a computer in
arbitrary order). Each machine is described by its performance (measured in computers per hour), input and output specification.

Input specification describes which parts must be present in a half-finished computer for the machine to be able to operate on it. The specification is a set of P numbers 0, 1 or 2 (one number for each part), where 0 means that corresponding part
must not be present, 1 — the part is required, 2 — presence of the part doesn't matter.

Output specification describes the result of the operation, and is a set of P numbers 0 or 1, where 0 means that the part is absent, 1 — the part is present.

The machines are connected by very fast production lines so that delivery time is negligibly small compared to production time.

After many years of operation the overall performance of the ACM Computer Factory became insufficient for satisfying the growing contest needs. That is why ACM directorate decided to upgrade the factory.

As different machines were installed in different time periods, they were often not optimally connected to the existing factory machines. It was noted that the easiest way to upgrade the factory is to rearrange production lines. ACM directorate decided to
entrust you with solving this problem.

Input

Input file contains integers P N, then N descriptions of the machines. The description of ith machine is represented as by 2 P + 1 integers Qi Si,1 Si,2...Si,P Di,1Di,2...Di,P,
where Qi specifies performance, Si,j — input specification for part j, Di,k — output specification for part k.

Constraints

1 ≤ P ≤ 10, 1 ≤ N ≤ 50, 1 ≤ Qi ≤ 10000

Output

Output the maximum possible overall performance, then M — number of connections that must be made, then M descriptions of the connections. Each connection between machines A and B must be described by three positive numbers A B W,
where W is the number of computers delivered from A to B per hour.

If several solutions exist, output any of them.

Sample Input
Sample input 1
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
Sample input 2
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
Sample input 3
2 2
100  0 0  1 0
200  0 1  1 1

Sample Output
Sample output 1
25 2
1 3 15
2 3 10
Sample output 2
4 5
1 3 3
3 5 3
1 2 1
2 4 1
4 5 1
Sample output 3
0 0

Hint

Bold texts appearing in the sample sections are informative and do not form part of the actual data.
Source

Northeastern Europe 2005, Far-Eastern Subregion

题目意思:

每台ACM计算机由P个部分组成,有N个机器用于组装ACM计算机,将其中若干台机器连在一起有可能能够组装成一台完整的ACM计算机。。
给出每个机器的容纳组装的ACM计算机的最大数量Q,输入和输出机器的P个部分,P个部分分别用0/1/2来表示,0表示这部分不能存在,1表示这部分是必需的,2表示这部分无关紧要(存不存在都可以)。
求最大的ACM计算机数量、连在一起使用的机器数、机器间传递的ACM计算机数目。

解题思路:

折腾了一下午…建图就超级麻烦…参考了Discuss中大神的思路:

①拆点,将一个机器拆分成两个点,即输入和输出两部分,流量是其容纳的最大数量Q;
(此时结点数N应该变成2*N)
②加一个超级源点和一个超级汇点
对于机器输入的P个部分,如果有的部分必须存在,即含1,那么将其与超级源点相连,看作超级源点向其传递数量INF;
对于机器输出的P个部分,如果有的部分必不存在,即含0,那么将其与超级汇点相连,看作其向超级汇点传出数量INF;
(此时结点数2*N应该变成2*N+2,但是下标是从0~2*N+1)

③机器间的互相传递是从A机器的输出传到B机器的输入
因为只有0和1是完全对立的,所以相应部分分别是0和1时两个机器之间必然不能传递,其他情况(0和0、1和1、2和2、0和2、1和2)均可,传递数量为INF。

单向图建立完毕后,我用了Edmond-Karp算法求解最大流,别的最大流算法也是可以的。
然后需要求解网络中的流向,在求最大流之前复制一下建图的数组,使用这两个数组比较机器A到B之间的流量,如果流量有减少说明需要使用该机器。因为题目是Special Judge,所以不用考虑顺序,可以使用STL的vector保存后输出即可。

#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<map>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 1010
struct Node
{
int in[11];
int out[11];
int q;
} s[MAXN];
struct node
{
int from,to,cap;
node(int a,int b,int c):from(a),to(b),cap(c) {}
};
vector<node> res;//记录网络流中机器之间的流量
int temp[MAXN][MAXN];
int capacity[MAXN][MAXN]; //记录残留网络的容量
int flow[MAXN];           //标记从源点到当前节点实际还剩多少流量可用
int pre[MAXN];            //标记在这条路径上当前节点的前驱,同时标记该节点是否在队列中
int n,p;                  //总结点数、组成部分数
queue<int> myqueue;
int BFS(int src,int des)
{
int i;
while(!myqueue.empty())       //队列清空
myqueue.pop();
for(i=0; i<=n+1; ++i)
pre[i]=-1;
pre[src]=0;
flow[src]= INF;
myqueue.push(src);
while(!myqueue.empty())
{
int index = myqueue.front();
myqueue.pop();
if(index == des)            //找到了增广路径
break;
for(i=0; i<=n+1; ++i)
{
if(i!=src && capacity[index][i]&& pre[i]==-1)
{
pre[i] = index; //记录前驱
flow[i] = min(capacity[index][i],flow[index]);   //关键:迭代的找到增量
myqueue.push(i);
}
}
}
if(pre[des]==-1)      //残留图中不再存在增广路径
return -1;
else
return flow[des];
}
int maxFlow(int src,int des)
{
int increasement= 0;
int sumflow = 0;
while((increasement=BFS(src,des))!=-1)
{
int k = des;          //利用前驱寻找路径
while(k!=src)
{
int last = pre[k];
capacity[last][k] -= increasement; //改变正向边的容量
capacity[k][last] += increasement; //改变反向边的容量
k = last;
}
sumflow += increasement;
}
return sumflow;
}

int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("F:/cb/read.txt","r",stdin);
//freopen("F:/cb/out.txt","w",stdout);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
int i,j;
while(cin>>p>>n)
{
int t=n;
n*=2;
memset(capacity,0,sizeof(capacity));
memset(flow,0,sizeof(flow));
for(i=1; i<=t; ++i)
{
cin>>s[i].q;
capacity[i][i+t]=s[i].q;//
bool b0=true,b1=true;
for(j=0; j<p; ++j)
{
cin>>s[i].in[j];
if(s[i].in[j]==1) b0=false;//存在1
}
for(j=0; j<p; ++j)
{
cin>>s[i].out[j];
if(!s[i].out[j]) b1=false;//存在0
}
if(b0) capacity[0][i]=INF;//超级源点0
if(b1) capacity[i+t][n+1]=INF;//超级汇点n+1
}
bool flag=true;
for(i=1; i<=t; ++i)
for(j=1; j<=t; ++j)
if(i!=j)
{
flag=true;
for(int k=0; k<p; ++k)
if(s[i].out[k]+s[j].in[k]==1)
{
flag=false;
break;
}
if(flag)
capacity[i+t][j]=INF;//机器之间
}
memcpy(temp,capacity,sizeof(temp));//复制capacity数组到temp
cout<<maxFlow(0,n+1)<<" ";
for(int i=1; i<=t; i++)
{
for(int j=1; j<=t; j++)
{
if(i!=j)
if(capacity[t+i][j]<temp[t+i][j])//流量有减少说明需要使用该机器
res.push_back(node(i,j,temp[t+i][j]-capacity[t+i][j]));
}
}
cout<<res.size()<<endl;
for(int i=0; i<res.size(); i++)
cout<<res[i].from<<" "<<res[i].to<<" "<<res[i].cap<<endl;
res.clear();
}
return 0;
}
/*
Sample input 1
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
Sample input 2
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
Sample input 3
2 2
100  0 0  1 0
200  0 1  1 1
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息