本题一个英国飞行员可以和特定的一个外国飞行员搭配,又要求求最佳的选人方式使选到的人最多,所以一看就是二分图的最大匹配,可以用匈牙利算法搞定。当然也可以建立网络流模型,首先建立源点S和汇点T,源点向所有英国飞行员连流量为1的边,再把所有英国飞行员和能与之搭配的外国飞行员间连一条流量为1的边,最后把所有外国飞行员向汇点T连一条流量为1的边,此时该模型的最大流等于二分图的最大匹配数。又因为要输出一种方案,如果用匈牙利算法就开一个flag数组进行标记,记录二分图左边能匹配右边的哪一个,最后for一遍输出。如果是网络流算法,就for一遍英国飞行员个数,如果它到右边有外国飞行员相连,并且能流的流量为0,说明是满流,说明是一种方案,最后输出就行啦。
匈牙利算法:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define M 211
using namespace std;
int n,m;
int dis[M][M],fy[M],mat[M];
int flag[M];
void init()
{
scanf("%d%d",&n,&m);
memset(dis,0,sizeof(dis));
memset(mat,-1,sizeof(mat));
memset(flag,-1,sizeof(flag));
int x,y;
while(scanf("%d%d",&x,&y)!=EOF&&x!=-1&&y!=-1)
dis[x][y]=1;
}
bool crosspath(int u)
{
for(int i=m+1;i<=n;i++)
{
if(dis[u][i]==1&&fy[i]==0)
{
fy[i]=1;
if(mat[i]==-1||crosspath(mat[i]))
{
flag[u]=i;
mat[i]=u;
return true;
}
}
}
return false;
}
int hungary()
{
int ans=0;
for(int i=1;i<=m;i++)
{
if(flag[i]==-1)
{
memset(fy,0,sizeof(fy));
ans+=crosspath(i);
}
}
return ans;
}
int main()
{
freopen("flyer.in","r",stdin);
freopen("flyer.out","w",stdout);
init();
int sum=hungary();
if(sum==0)
printf("No Solution!\n");
else
{
printf("%d\n",sum);
/*for(int i=1;i<=m;i++)
{
if(flag[i]!=-1)
printf("%d %d\n",i,flag[i]);
}*/
//输出匹配方案
}
return 0;
}
网络流模型:
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define M 211*211
#define INF 0x7fffffff
using namespace std;
int n,m;
int num=0;
int p[M];
int q[4*M];
int level[M];
struct node
{
int a;
int b;
int w;
int next;
}str1[M];
void add(int x,int y,int z)
{
str1[num].a=x;
str1[num].b=y;
str1[num].w=z;
str1[num].next=p[x];
p[x]=num++;
}
void init()
{
scanf("%d%d",&m,&n);
memset(p,-1,sizeof(p));
int x,y;
while(scanf("%d%d",&x,&y)!=EOF&&x!=-1&&y!=-1)
{
add(x,y,1);
add(y,x,0);
}
}
bool makelevel(int st,int ed)
{
memset(level,0,sizeof(level));
level[st]=1;
int l=0,r=0;
q[r++]=st;
while(l<r)
{
int k=q[l++];
if(k==ed)
return true;
for(int i=p[k];i!=-1;i=str1[i].next)
{
int v=str1[i].b;
if(!level[v]&&str1[i].w)
{
level[v]=level[k]+1;
q[r++]=v;
}
}
}
return false;
}
int dfs(int now,int maxf,int ed)
{
if(now==ed)
return maxf;
int ret=0,sf;
for(int i=p[now];i!=-1;i=str1[i].next)
{
int v=str1[i].b;
if(str1[i].w&&level[v]==level[now]+1)
{
int minx=min(maxf-ret,str1[i].w);
sf=dfs(v,minx,ed);
str1[i].w-=sf;
str1[i^1].w+=sf;
ret+=sf;
if(ret==maxf)
return ret;
}
}
return ret;
}
int dinic(int st,int ed)
{
int ans=0;
while(makelevel(st,ed))
ans+=dfs(st,INF,ed);
return ans;
}
int main()
{
//freopen("flyer.in","r",stdin);
//freopen("flyer.out","w",stdout);
init();
for(int i=1;i<=m;i++)
{
add(200,i,1);
add(i,200,0);
}
for(int i=m+1;i<=n;i++)
{
add(i,300,1);
add(300,i,0);
}
printf("%d\n",dinic(200,300));
for(int i=1;i<=m;i++)
{
for(int j=p[i];j!=-1;j=str1[j].next)
{
if(str1[j].w==0&&str1[j].b!=0&&j%2==0)
printf("%d %d\n",i,str1[j].b);
}
}
return 0;
}