问题描述:
第二次世界大战时期, 英国皇家空军从沦陷国征募了大量外籍飞行员。 由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的 2 名飞行员, 其中 1 名是英国飞行员,另 1 名是外籍飞行员。 在众多的飞行员中, 每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。 如何选择配对飞行的飞行员才能使一次派出最多的飞机。 对于给定的外籍飞行员与英国飞行员的配合情况, 试设计一个算法找出最佳飞行员配对方案, 使皇家空军一次能派出最多的飞机。
任务:
对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
数据输入:
文件第 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!’ 。
样例输入:
5 10
1 7
1 8
2 6
2 9
2 10
3 7
3 8
4 7
4 8
5 10
-1 -1
样例输出:
4
1 7
2 9
3 8
5 10
标准的二分图最大匹配问题,不过由于答案不唯一,所以上面的样例输出的却只是个"样例输出"
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define maxn 110
int mat[maxn][maxn];
int vis[maxn], link[maxn];
int n, m;
bool find(int u)
{
for(int i = 1; i <= m; i++)
{
if(mat[u][i] && !vis[i])
{
vis[i] = 1;
// i还未匹配过或在上一个匹配中有增广路
if(link[i] == -1 || find(link[i]))
{
link[i] = u;
return true;
}
}
}
return false;
}
int maxmatch()
{
int re = 0;
for(int i = 1; i <= n; i++)
{
memset(vis, 0, sizeof(vis));
if(find(i))
re++;
}
return re;
}
int main()
{
int a, b;
while(~scanf("%d%d", &n, &m))
{
memset(mat, 0, sizeof(mat));
while(scanf("%d%d", &a, &b))
{
if(a == -1 && b == -1)break;
mat[a][b-n] = 1;
}
memset(link, -1, sizeof(link));
int re = maxmatch();
if(!re)
printf("No Solution!\n");
else
{
printf("re = %d\n", re);
for(int i = 1; i <= m-n; i++) // 输出一组可行解
{
if(link[i] > 0)
{
printf("%d %d\n", link[i], n+i);
}
}
}
}
return 0;
}