第二次世界大战时期,英国皇家空军从沦陷国征募了大量外籍飞行员。由皇家空军派出的每一架飞机都需要配备在航行技能和语言上能互相配合的2名飞行员,其中1名是英国飞行员,另1名是外籍飞行员。在众多的飞行员中,每一名外籍飞行员都可以与其他若干名英国飞行员很好地配合。如何选择配对飞行的飞行员才能使一次派出最多的飞机。对于给定的外籍飞行员与英国飞行员的配合情况,编程找出一个最佳飞行员配对方案,使皇家空军一次能派出最多的飞机。
Input
第1行有2个正整数 m 和 n。n 是皇家空军的飞行 员总数(n<100);m 是外籍飞行员数。外籍飞行员编号为 1~m;英国飞行员编号为 m+1~n。接下来每行有 2 个正整数 i 和 j,表示外籍飞行员 i 可以和英国飞行员 j 配合。输入最后以 2 个-1 结束。
Output
第 1 行是最佳飞行 员配对方案一次能派出的最多的飞机数 M。如果所求的最佳飞行员配对方案不存在,则输出‘No Solution!’。
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
Output示例
4
分析:
明显是一道最裸的 ——二分图最大匹配数 问题。用 匈牙利算法。。
如图 就是二分图。
每个u可以和多个v进行匹配,
所谓的二分图最大匹配,就是在每个u只能与一个v进行匹配的前提下,求最大匹配数。
匈牙利算法:
本来是无向图,可以看成是有向的,从 u 指向 v。
用递归,第一次做二分图的题,代码上详解。。
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
vector<int> pic[110]; //vector存原始二分图。
bool vis[110]; //每次搜索前都要初始化,记录该次搜索中每个m是否已经搜索过。
int match[110]; //存相匹配信息,没有匹配为 -1。
bool find_m(int n) //返回能否找到与 n匹配的m(也就是n是左面的元素,m是右面的元素)
{
for(int i = 0;i < pic[n].size();i ++)
{
int m = pic[n][i]; //当前的m,也就是n所能匹配的其中一个m。
if(!vis[m]) //如果没有访问过这个m
{
vis[m] = true;
if(match[m] == -1 || find_m(match[m])) //如果该m没有匹配,或 当前与该m匹配的n还能匹配其它的m
{
match[m] = n;
return true; //匹配成功
}
}
}
return false; //匹配失败
}
int main()
{
int m,n;
int a,b;
int sum = 0;
cin>>m>>n;
while(cin>>a>>b && (a != -1 || b != -1)) //先存图
{
pic[a].push_back(b);
}
for(int i = 1;i <= n;i ++) //初始化
match[i] = -1;
for(int i= 1;i <= m;i ++)
{
memset(vis,0,sizeof(vis)); //初始化
if(find_m(i))
sum++;
}
cout<<sum<<endl;
return 0;
}