【匈牙利算法】P3386 【模板】二分图最大匹配

给定一张二分图,其左部点集大小为 n,右部点集大小为 m,请求出其最大匹配。

对于以上问题,匈牙利算法给出的解决方案为,对于每个节点u,先匹配它第一条边,若对应的v还没被匹配,就可以顺理成章的将u、v匹配上,进行下一个u的匹配;若此时的v已经被之前的u'匹配上了,那么就看u'能否有其他的选择,如果有就可以让u'退让,连v',然后u就可以连v了;如果u'没有其他选择,那就不让,使得u没有对应的匹配

大概的思路就是这样

其实也可以用网络流解决,将左部的节点连一个超级源点,右部的点全部连一个超级汇点,左部右部之间正常建边,将这些边的边权全部赋为1,然后dinic解决即可

匈牙利算法代码

#include<bits/stdc++.h>
using namespace std;
vector <int> G[1005];
int t,n,m,vis[1005],mat[1005];
bool dfs(int u)
{
	if(vis[u]==1) return false;
	vis[u]=1;
	for(int k=0;k<G[u].size();k++)
		if(mat[G[u][k]]==0 || dfs(mat[G[u][k]]))
		{
			mat[G[u][k]]=u;
			return true;
		}
	return false;
}
int main()
{
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	scanf("%d%d%d",&n,&m,&t);
	int x,y;
	for(int i=1;i<=t;i++)
		scanf("%d%d",&x,&y),G[x].push_back(y);
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		if(dfs(i)) ans++;
		memset(vis,0,sizeof(vis));
	}
	printf("%d\n",ans);
	return 0;
}

注意这个vis数组要每次清零

猜你喜欢

转载自blog.csdn.net/andyc_03/article/details/107715503