51Nod-2006-飞行员配对(二分图最大匹配)
如题,这种题我以前见过,但是作为菜鸟当然做不出来,而今天既然再次遇见,便打算将其搞清楚。遂网上搜索解法,但见满篇代码,却不见有谁讲清楚到底是怎么一回事。大佬们一句裸题就放代码了,可是小白不懂啊~
于是便有了如下经历,终于花了两个小时A掉了
首先,这是一道数据流的题,但我不会数据流,以后学到了再说。但此题还有另一种解法,其名为匈牙利算法。这让我联想到匈牙利命名法,但其实并没有什么关系。唔,我就是用匈牙利算法来解的这道题。
不了解匈牙利算法的童鞋,去看这位大佬的博客:匈牙利算法
他的代码乍一看是看不懂的,因为不完整,但是算法思想讲的很透彻,看懂思想即可。
接下来是针对这道题的解法了,到现在才发现确实没什么好说的,直接拿匈牙利算法套进去就是答案,不过还是根据我的代码解释一下。
三个数组,a[x][y]=1
表示外籍飞行员x能够和英国飞行员y相配合,如果等于0就是不能配合了。
used[x]数组是直接参考了上面博客的,即在对某一个外籍飞行员找搭档的时候,如果已经找过英国飞行员x了,但是x已经和别的外籍飞行员配对了,就需要递归查找x的原配是不是还能和别人配对吧,既然是别人就当然不能再匹配到x了,所以used[x]数组就起到这个作用。
eng[x]数组就表示英国飞行员x是不是已经和别人配对了,这里需要默认给它全置为-1(而不是0),为什么?因为外籍飞行员有0号呀。
然后就很好理解了,看代码看完就懂
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define MAX_LEN 500
#define MOD 1000000007
int a[MAX_LEN][MAX_LEN] = {0};
int used[MAX_LEN] = {0};
int eng[MAX_LEN] = {-1};
int sum = 0;
void init()
{
memset(used,0,sizeof(used));
}
bool pp(int x,int m,int n)
{
int i,j;
for(i=m;i<n;i++)
{
if(a[x][i] == 1 && used[i] == 0)
{
used[i] = 1;
if(eng[i] == -1 || pp(eng[i],m,n))
{
eng[i] = x;
return true;
}
}
}
return false;
}
int main()
{
int m,n;
int w,y;
cin>>w>>y;
while(cin>>m>>n)
{
if(m==-1 || n==-1)
{
break;
}
a[m-1][n-1] = 1;
}
memset(eng,-1,sizeof(eng));
for(int i=0;i<w;i++)
{
init();
if(pp(i,w,y))
{
sum++;
}
}
cout<<sum<<endl;
}