二分图最大匹配 匈牙利算法的简单理解

(本文图片及被*标注内容来自CSDN博客:pi9nc)

基本概念—二分图

二分图:是图论中的一种特殊模型。若能将无向图G=(V,E)的顶点V划分为两个交集为空的顶点集,并且任意边的两个端点都分属于两个集合,则称图G为一个为二分图。


匹配:一个匹配即一个包含若干条边的集合,且其中任意两条边没有公共端点。如下图,图3的红边即为图2的一个匹配。

二分图最大匹配 匈牙利算法的简单理解_第1张图片二分图最大匹配 匈牙利算法的简单理解_第2张图片

匹配边/匹配点:包含在匹配中的边及其端点。

非匹配边/非匹配点:不包含在匹配中的边及其端点。

最大匹配所含边数最多的匹配称为最大匹配。*

基本概念—匈牙利算法

交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边...形成的路径叫交替路。*

增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替路称为增广路(agumenting path)。

匈牙利算法

由增广路的性质,增广路中的匹配边总是比未匹配边多一条,所以如果我们放弃一条增广路中的匹配边,选取未匹配边作为匹配边,则匹配的数量就会增加。匈牙利算法就是在不断寻找增广路,如果找不到增广路,就说明达到了最大匹配。

算法模板(邻接表 & C++)

#include
using namespace std;

const int N=20000,M=20000;

struct edge{int u,v; edge *next;}e[M],*P=e,*point[N];
int Link[N],used[N],n,m;

inline void add_edge(int u,int v)
{
	++P;
	P->u = u; P->v = v; P->next = point[u]; point[u] = P;
}

bool dfs(int u)
{
	for(edge *j=point[u];j;j=j->next)
	{
		if(used[j->v])	continue;
		used[j->v]=true;
		if(Link[j->v]==0 || dfs(Link[j->v]))
		{
			Link[j->v]=u;
			return true;
		}
	}
	return false;
}

int main()
{
	//读入数据
	memset(Link,0,sizeof(Link));
	int cnt=0;
	for(int i=1;i<=n;i++)
	{
		memset(used,0,sizeof(used));
		if(dfs(i))	cnt++;
	}
	cout<


你可能感兴趣的:(图论,Notes,图论,算法,匈牙利算法,二分图匹配,最大匹配)