hihocoder 1122 : 二分图二•二分图最大匹配之匈牙利算法

时间:2022-07-25 05:55:19

首先,匈牙利算法是用来求二分图的最大匹配的,它的核心问题就是找增广路径。匈牙利算法的时间复杂度为O(VE),其中

V为二分图左边的顶点数,E为二分图中边的数目。


现在我们来看看增广路有哪些性质:


(1)有奇数条边。

(2)起点在二分图的左半边,终点在右半边。

(3)路径上的点一定是一个在左半边,一个在右半边,交替出现。

(4)整条路径上没有重复的点。

(5)起点和终点都是目前还没有配对的点,而其它所有点都是已经配好对的。

(6)路径上的所有第奇数条边都不在原匹配中,所有第偶数条边都出现在原匹配中。

(7)最后,也是最重要的一条,把增广路径上的所有第奇数条边加入到原匹配中去,并把增广路径中的所有第偶数条边从原

匹配中删除(这个操作称为增广路径的取反),则新的匹配数就比原匹配数增加了1个。


当然,匹配开始时我们任意选择一边的所有点为起始点找增广路径,由增广路的性质可以看出,每找到一条增广路径,匹配

数增加1。


求增广路的方法是用递归的思想,从已知的匹配结果当中去寻找是否还能够给当前节点留出一个位置来匹配。。。。


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

const int maxn = 1001;
int n,m,belong[maxn];
bool line[maxn][maxn],vis[maxn];

bool find(int x)
{
for(int j = 1; j <= n; j++)
{
if(line[x][j] == true && vis[j] == false)
{
vis[j] = true;
if(belong[j] == 0 || find(belong[j]) == true)
{
belong[j] = x;
return true;
}
}
}
return false;
}

int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i = 1; i <= m; i++)
{
int u,v;
scanf("%d%d",&u,&v);
line[u][v] = line[v][u] = true;
}
int ans = 0;
memset(belong,0,sizeof(belong));
for(int i = 1; i <= n; i++)
{
memset(vis,false,sizeof(vis));
if(find(i)) ans++;
}
printf("%d\n",ans/2);//由于是对每个节点都进行了一次匹配,所以最后的结果要除以2。。
}
return 0;
}