Description
第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2 名飞行员,其中1 名是英国飞行员,另1 名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
Input Description
由文件input.txt提供输入数据。文件第1 行有2个正整数m和n。n是皇家空军的飞行员总数(n<100);m是外籍飞行员数。外籍飞行员编号为1~m;英国飞行员编号为m+1~n。接下来每行有2 个正整数i和j,表示外籍飞行员i可以和英国飞行员j配合。文件最后以2个-1 结束。
Output Description
程序运行结束时,将最佳飞行员配对方案输出到文件output.txt 中。第1 行是最佳飞行员配对方案一次能派出的最多的飞机数M。
Sample Input
5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1
Sample Output
4
1 7
2 9
3 8
5 10
该题为二分图最大匹配问题,可以用匈牙利算法解决,也可以直接用最大流,转化为多源点多汇点问题。
建模方法:
1.设置一个超级源点S,设置一个超级汇点T。
2.从S向每个外籍飞行员连一条边,容量为1。
3.从每个皇家飞行员向T连一条边,容量为1。
4.根据输入,从每个外籍飞行员向皇家飞行员 连一条容量为1的边。
对该网络求从S到T的最大流。
/*
Name:wxjlzbcd
Memory:6340KB
Time:11ms
*/
#include<cstdio>
#include<climits>
#include<cstring>
#include<algorithm>
const int MAXN=20010;
const int MAXM=500010;
using namespace std;
struct edge
{
int v,next,val;
}e[MAXM];
int p[MAXN],eid;
int n,m;
int h[MAXN];
int gap[MAXN];
int S,T;
inline void add(int from,int to,int val)
{
e[eid].v=to;e[eid].val=val;
e[eid].next=p[from];
p[from]=eid++;
}
inline int dfs(int pos,int cost)
{
if(pos==T)
return cost;
int j,minh=n-1,lv=cost,d;
for(j=p[pos];j!=-1;j=e[j].next)
{
int v=e[j].v,val=e[j].val;
if(val>0)
{
if(h[v]+1==h[pos])
{
if(lv<e[j].val)
d=lv;
else
d=e[j].val;
d=dfs(v,d);
e[j].val-=d;
e[j^1].val+=d;
lv-=d;
if(h[S]>=n)
return cost-lv;
if(lv==0)
break;
}
if (h[v]<minh)
minh=h[v];
}
}
if (lv==cost)
{
--gap[h[pos]];
if(gap[h[pos]]==0)
h[S]=n;
h[pos]=minh+1;
++gap[h[pos]];
}
return cost-lv;
}
int isap(int st,int ed)
{
S=st;
T=ed;
int ret=0;
memset(gap,0,sizeof(gap));
memset(h,0,sizeof(h));
gap[st]=n;
while(h[st]<n)
ret+=dfs(st,INT_MAX);
return ret;
}
int main()
{
freopen("air.in","r+",stdin);
freopen("air.out","w+",stdout);
scanf("%d%d",&m,&n);
memset(p,-1,sizeof(p));
eid=0;
int i;
int tnum=m+n+2;
for(i=2;i<=m+1;++i)
{
add(1,i,1);
add(i,1,0);
}
for(i=m+2;i<=tnum;++i)
{
add(i,tnum,1);
add(tnum,i,0);
}
while(1)
{
int u,v,c;
scanf("%d%d",&u,&v);
if(u==-1&&v==-1)
break;
++u;
++v;
v+=m;
add(u,v,1);
add(v,u,0);
}
printf("%d\n",isap(1,tnum));
return 0;
}
原文地址:http://blog.csdn.net/wxjlzbcd/article/details/43530389