题意
给出n个飞行员,其中有m个外籍的,给出它们的几个匹配关系,求出最多能匹配多少组。
思路
这题可以用二分图的最大匹配,但是这里是网络流的题目,所以我这写的是网络流的。建一个源点连本国的飞行员,汇点连外籍的飞行员,跑一边最大流就求得出答案了。
代码
#include<cstdio>
#define min(a,b) a>b?b:a
#define max(a,b) a>b?a:b
int s,t,m,n,x,y,d,b[101],f[101][101],c[101][101],ans;
int find(int k)
{
if (k==t) return 1;
for (int i=0;i<=n+1;i++)
{
if (b[i]==-1&&(c[k][i]>f[k][i]||f[i][k]>0))
{
b[i]=k;
if (find(i)) return 1;
}
}
return 0;
}
void add()
{
d=2147483647;
int i=t;
while (i!=s)
{
if (c[b[i]][i]>0) d=min(d,c[b[i]][i]-f[b[i]][i]);
if (c[i][b[i]]>0) d=min(d,f[i][b[i]]);
i=b[i];
}
i=t;
while (i!=s)
{
if (c[b[i]][i]>0) f[b[i]][i]+=d;
if (c[i][b[i]]>0) f[i][b[i]]-=d;
i=b[i];
}
ans+=d;
}
int main()
{
scanf("%d%d",&m,&n);
while (scanf("%d%d",&x,&y),x!=-1||y!=-1) c[x][y]=1;
s=0;t=n+1;//设源点和汇点
for (int i=1;i<=m;i++)
{
b[i]=-1;//初始化
c[s][i]=1;//源点连本国的
}
for (int i=m+1;i<=n+1;i++)
{
b[i]=-1;
c[i][t]=1;//连外国的
}
b[s]=0;
while (find(s))//一直找增广路,然后更新流量
{
add();
for (int i=1;i<=n+1;i++)
b[i]=-1;
}
printf("%d\n",ans);//方案数
for (int i=1;i<=m;i++)
{
for (int j=m+1;j<=n;j++)
if (f[i][j]) {printf("%d %d\n",i,j);break;}//如果这条路之间有流量的话说明它们匹配了
}
}