题意:一家公司有n台机器用来生产电脑,一个电脑有p个部分,要p个部分同时存在才算生产完成。对于一个机器,有三组数据描述。数据一:一个整数Q,用来表示机器一个小时能够加工多少电脑,数据二:(输入)p个整数,整数取值为0,1,2,用以表示电脑需满足这一组条件才能被这台机器加工。0表示这个部分不能有,1表示这个部分必须有,2表示这个部分可有可无。数据三:(输出)p个整数,整数取值为0,1。用以表示输出的电脑的状态,0表示这部分没有,1表示这部分有。可能数据二,三说得不是很清楚,举个例子:一台电脑由3个部分组成,某一台机器的数据二为(0,0,0),数据三为(1,0,1)。则表示这台机器只能加工第一部分,第二部分,第三部分均不存在的电脑,加工后这电脑有了第一部分,第三部分,缺失第二部分。然后题目要求将机器练成生产线,使得效率最大。输出还是很好理解的吧。
思路:这里我们需要建图,然后用最大流。我们将n台机器拆成2*n个点,如机器i拆成点i,和点i+n,点i表示输入,点i+n表示输出,然后我们多加两个点,源点s,汇点e。若机器i的输入全为0,则将点i与源点s相连,权值为MaxInt。若机器i的输出全为1,则将点i+n与汇点e相连,权值为MaxInt。之后再将点i与点i+n相连,权值为机器一小时加工电脑的数目Q。最后若机器i的输出与机器j的输入相等的话,则将点i+n与点j相连。建完图后,套个模板就可以了。
AC代码:
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
#define inf 9999999
struct data
{
int x,y,value;
}ans[505];
int p,k;
int map[205][205];
int cnt,ca[55];
int path[505];
bool findMaxflow()
{
bool visited[505]={0};
memset(path,0,sizeof(path));
queue<int> qu;
qu.push(0); visited[0]=1;
while(!qu.empty())
{
int pos = qu.front();
qu.pop();
if(pos==2*k+1) return 1;
for(int i=0;i<=2*k+1;i++)
{
if(!visited[i]&&map[pos][i]>0)
{
qu.push(i);
visited[i]=1;
path[i]=pos;
}
}
}
return 0;
}
void modifyMap(int &add)
{
int pos = 2*k+1;
add = inf;
while(pos)
{
if(add>map[path[pos]][pos])
add=map[path[pos]][pos];
pos = path[pos];
}
pos = 2*k+1;
while(pos)
{
map[path[pos]][pos]-=add;
map[pos][path[pos]]+=add;
pos = path[pos];
}
}
int main()
{
while(scanf("%d%d",&p,&k)!=EOF)
{
memset(map,0,sizeof(map));
int input[55][15],output[55][15];
cnt=0;
for(int i=1;i<=k;i++)
{
scanf("%d",&ca[i]);
for(int j=0;j<p;j++)
scanf("%d",&input[i][j]);
for(int j=0;j<p;j++)
scanf("%d",&output[i][j]);
}
for(int i=1;i<=k;i++)
{
int j;
for(j=0;j<p;j++)
if(output[i][j]==0) break;
if(j>=p) map[i+k][2*k+1]=inf;
for(j=0;j<p;j++)
if(input[i][j]==1) break;
if(j>=p) map[0][i]=inf;
map[i][i+k]=ca[i];
}
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
if(i==j) continue;
int l;
for(l=0;l<p;l++)
{
if(input[j][l]==2) continue;
if(output[i][l]!=input[j][l]) break;
}
if(l>=p) map[i+k][j]=inf;
}
}
int sum=0; int add;
while(findMaxflow())
{
modifyMap(add);
sum+=add;
}
printf("%d ",sum);
for(int i=1;i<=k;i++)
{
for(int j=1;j<=k;j++)
{
if(i==j) continue;
if(map[j][i+k]>0)
{
ans[cnt].x=i;
ans[cnt].y=j;
ans[cnt++].value=map[j][i+k];
}
}
}
printf("%d\n",cnt);
for(int i=0;i<cnt;i++)
printf("%d %d %d\n",ans[i].x,ans[i].y,ans[i].value);
}
return 0;
}