SSL-ZYC 2601 (洛谷P1756)【24题】飞行员配对方案问题
题目大意:
思路:
网络流!
这道题最难的是建图,建好图了就基本都搞定了。
建图步骤:
1.设定起始点和结束点,分别是点0和点。
2.将与点1到相连,与点到相连,边权为1。
3.将两两读入的飞行员相连,边权为1。
然后就开始套模板啦。。。
代码:
#include <cstdio>
#include <iostream>
using namespace std;
const int inf=999999999;
int f[201][201],c[201][201],b[201],n,m,s,t,x,y,d,sum;
int dfs(int x) //深搜寻找增广路
{
if (x==t) return 1; //有增广路
for (int i=0;i<=t;i++)
if (b[i]==-1&&(f[i][x]>0||c[x][i]-f[x][i]>0))
{
b[i]=x;
if (dfs(i)==1) return 1; //有增广路
}
return 0;
}
void addflow() //寻找增广路中的最小边权
{
int i;
d=inf;
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];
}
sum+=d; //加上最小边权
return;
}
int main()
{
scanf("%d%d",&m,&n);
while (1)
{
scanf("%d%d",&x,&y);
if (x==-1&&y==-1) break;
c[x][y]=1;
}
s=0;
t=n+1; //加入起始点和结束点
for (int i=1;i<=t;i++)
{
b[i]=-1; //初始化
if (i<=m) c[s][i]=1;
else c[i][t]=1;
}
b[s]=0;
while (dfs(s)==1)
{
addflow(); //寻找增广路中的最小边权
for (int i=1;i<=t;i++)
b[i]=-1; //重新初始化,准备下一次寻找增广路
b[s]=0;
}
printf("%d\n",sum);
for (int i=1;i<=m;i++)
for (int j=m+1;j<=n;j++) //第二问
if (f[i][j]>0)
{
printf("%d %d\n",i,j);
break;
}
return 0;
}