题目链接:http://poj.org/problem?id=3436
题意:题意看了好长时间。。。有一些机器来组装电脑,每台电脑有P个部分,P个部分全部组装完成才算完成。每台机器要求输入一定规格的半成品电脑,输出一定规格的电脑,每台机器有最大产出效率(每小时生产台数),要求合理安排这些机器使得总的生产效率最大。
题解:感觉是网络流,但是开始不知道怎么建模,看了别人的博客,拆点,真是巧妙,将每个点(机器)拆成两个点,出点和入点,在入点和出点之间添加容量即生产效率。在添加一个源点和一个汇点,将全0的入点和源点连接,全1的出点和汇点连接。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int MAX=50*2+10;
const int INF=0x3f3f3f3f;
int in[MAX/2][15],out[MAX/2][15];
int flow[MAX][MAX],cap[MAX][MAX];
int res[MAX],pre[MAX];
int N;//点的数目
int P;
int match(int *a,int *b)
{
int flag=1;
for(int i=1;i<=P;i++)
{
if(a[i]==b[i]) continue;
if(a[i]==2) continue;
if(b[i]==2) continue;
flag=0;
break;
}
return flag;
}
int matchS(int *a)
{
for(int i=1;i<=P;i++)
if(a[i]==1)
return 0;
return 1;
}
int matchE(int *a)
{
for(int i=1;i<=P;i++)
if(a[i]==0)
return 0;
return 1;
}
int EK(int s,int e)
{
int ans=0;
queue<int>que;
while(1)
{
memset(res,0,sizeof(res));
que.push(s);
while(!que.empty())
{
int u=que.front();
res[s]=INF;
que.pop();
for(int v=0;v<N;v++)
{
if(!res[v]&&cap[u][v]>flow[u][v])
{
pre[v]=u;
que.push(v);
res[v]=min(res[u],cap[u][v]-flow[u][v]);
}
}
}
if(res[e]==0) break;
ans+=res[e];
for(int i=e;i!=s;i=pre[i])
{
flow[pre[i]][i]+=res[e];
flow[i][pre[i]]-=res[e];
}
}
return ans;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n;
while(scanf("%d%d",&P,&n)!=EOF)
{
memset(flow,0,sizeof(flow));
memset(cap,0,sizeof(cap));
N=2*n+2;
for(int i=1;i<=n;i++)
{
int c;
scanf("%d",&c);
cap[2*i-1][2*i]+=c;
for(int j=1;j<=P;j++)
scanf("%d",&in[i][j]);
for(int j=1;j<=P;j++)
scanf("%d",&out[i][j]);
}
int s=0,e=N-1;
for(int i=1;i<=n;i++)
{
if(matchS(in[i])) cap[s][2*i-1]=INF;
if(matchE(out[i])) cap[2*i][e]=INF;
for(int j=1;j<=n;j++)
{
if(j==i) continue;
if(match(in[i],out[j])) cap[2*j][2*i-1]=INF;
}
}
printf("%d ",EK(s,e));
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
if(flow[2*i][2*j-1]!=0&&flow[2*i][2*j-1]!=INF)
ans++;
}
}
printf("%d\n",ans);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j) continue;
if(flow[2*i][2*j-1]!=0&&flow[2*i][2*j-1]!=INF)
printf("%d %d %d\n",i,j,flow[2*i][2*j-1]);
}
}
}
return 0;
}