问题描述:
第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出
的每一架飞机都需要配备在航行技能和语言上能互相配合的 2 名飞行员, 其中 1 名是英国飞
行员,另 1 名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英
国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的
外籍飞行员与英国飞行员的配合情况,试设计一个算法找出最佳飞行员配对方案,使皇家空
军一次能派出最多的飞机。
´编程任务:
对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,
使皇家空军一次能派出最多的飞机。
´数据输入:
由文件 input.txt 提供输入数据。文件第 1 行有 2 个正整数 m 和 n。n 是皇家空军的飞行
员总数(n<100);m 是外籍飞行员数。外籍飞行员编号为 1~m;英国飞行员编号为 m+1~n。
接下来每行有 2 个正整数 i 和 j,表示外籍飞行员 i 可以和英国飞行员 j 配合。文件最后以 2个-1 结束。
´结果输出:
程序运行结束时,将最佳飞行员配对方案输出到文件 output.txt 中。第 1 行是最佳飞行
员配对方案一次能派出的最多的飞机数 M。接下来 M 行是最佳飞行员配对方案。每行有 2
个正整数 i 和 j,表示在最佳飞行员配对方案中,飞行员 i 和飞行员 j 配对。
如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’ 。
输入文件示例 input.txt
5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1
输出文件示例 output.txt
4
1 7
2 9
3 8
5 10
题解:这道题是很明显的二分图最大匹配,匈牙利算法可解,不会的话网络流的最大流也是可以的。
建图方式:建超级源s以及超级汇t,s到x子集连一条容量为1的边,x子集到y子集原来已有的边不变,容量为无限大,y子集到t连一条容量为1的边
方法:最大流
P.S.这道题还要输出方案,这个好办,把x和y之间流量为1的边输出即可
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <float.h>
using namespace std;
const int Maxm=105;
const int oo=2147483647;
int s,i,u,v,t,len,n,m;
int head[Maxm];
int cur[Maxm];
int d[Maxm];
int vis[Maxm];
struct edge{
int u,v,c,f,next;
edge(){
u=v=c=f=0;next=-1;
}
edge(int x,int y,int z,int a,int b){
u=x;v=y;c=z;f=a;next=b;
}
} e[1000005];
void add(int u,int v,int c,int f){
len++;
e[len]=edge(u,v,c,f,head[u]);
head[u]=len;
}
int bfs(){
int i,x;
queue <int> q;
q.push(s);
for(i=1;i<=n+m+2;i++)
vis[i]=0;
d[s]=1;
vis[s]=1;
while(!q.empty()){
x=q.front();
q.pop();
for(i=head[x];i!=-1;i=e[i].next)
if(!vis[e[i].v]&&e[i].f<e[i].c){
q.push(e[i].v);
vis[e[i].v]=1;
d[e[i].v]=d[x]+1;
}
}
return vis[t];
}
int dfs(int x,int a){
if(x==t||a==0)
return a;
int f,flow=0;
int &i=cur[x];
for(;i!=-1;i=e[i].next)
if(d[e[i].v]==d[x]+1&&
(f=dfs(e[i].v,min(a,e[i].c-e[i].f)))){
flow+=f;
e[i].f+=f;
e[i^1].f-=f;
a-=f;
if(a==0)
break;
}
return flow;
}
int dinic(){
int flow=0;
while(bfs()){
for(i=1;i<=n+m+2;i++)
cur[i]=head[i];
flow+=dfs(s,oo);
}
return flow;
}
int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
scanf("%d %d",&n,&m);
len=-1;
for(i=1;i<=n+m+2;i++)
head[i]=-1;
for(i=1;i<=n;i++){
add(1,1+i,1,0);
add(1+i,1,0,0);
}
for(i=1;i<=m;i++){
add(1+n+i,n+m+2,1,0);
add(n+m+2,1+n+i,0,0);
}
while(1){
scanf("%d %d",&u,&v);
if(u==-1&&v==-1)
break;
add(u+1,v+1+n,oo,0);
add(v+1+n,u+1,0,0);
}
s=1;t=n+m+2;
printf("%d\n",dinic());
//for(i=0;i<=len;i++)
// printf("%d:%d %d %d %d\n",i,e[i].u,e[i].v,e[i].c,e[i].f);
return 0;
}