编程语言
首页 > 编程语言> > 一般图最大匹配(奇环处理) 带花树算法

一般图最大匹配(奇环处理) 带花树算法

作者:互联网

P6113 【模板】一般图最大匹配

匈牙利算法最大的问题在于无法处理带奇环的图,如果存在奇环,那么程序会T掉

带花树算法就是用于处理奇环的问题

#include <bits/stdc++.h>
#define inf 0x7fffffff
#define ll long long
//#define int long long
//#define double long double
#define re register int
#define void inline void
#define eps 1e-5
//#define mod 1e9+7
#define ls(p) p<<1
#define rs(p) p<<1|1
//#define ls(p) e[p].l
//#define rs(p) e[p].r
//#define pi acos(-1.0)
#define pb push_back
#define P pair < int , int >
#define mk make_pair
#define fi first
#define se second
using namespace std;
const int mod=998244353;
const int N=1e5+5;//?????????? 4e8.
int n,m;
namespace GP
{
	queue < int > q;
	struct node
	{
		int ver,next;
	}e[N];
	int tot,head[N];
	int num=0;
	int fa[N],v[N],pre[N],match[N],dfn[N];
	void add(int x,int y)
	{
		e[++tot].ver=y;
		e[tot].next=head[x];
		head[x]=tot;
	}
	void addedge(int x,int y)
	{
		add(x,y);add(y,x);
	}
	int get(int x)
	{
		return fa[x]==x?x:fa[x]=get(fa[x]);
	}
	int lca(int x,int y)
	{
		num++;
		x=get(x),y=get(y);
		while(dfn[x]!=num)
		{
			dfn[x]=num;
			x=get(pre[match[x]]);
			if(y)  swap(x,y);
		}
		return x;
	}
	void blossom(int x,int y,int z)
	{
		while(get(x)!=z)
		{
			pre[x]=y;y=match[x];
			if(v[y]==2)
			{
				v[y]=1;
				q.push(y);
			}
			if(x==get(x))  fa[x]=z;
			if(y==get(y))  fa[y]=z;
			x=pre[y];
		}
	}
	bool bfs(int s)
	{
		while(q.size())  q.pop();
		for(re i=1;i<=n;i++)  fa[i]=i,v[i]=pre[i]=0;
		v[s]=1,q.push(s);
		while(q.size())
		{
			int x=q.front();q.pop();
			for(re i=head[x];i;i=e[i].next)
			{
				int y=e[i].ver;
				if(v[y]==2||get(x)==get(y))  continue;
				if(!v[y])
				{
					v[y]=2;pre[y]=x;
					if(!match[y])
					{
						for(re u=y,lst;u;u=lst)
						{
							lst=match[pre[u]];
							match[u]=pre[u];
							match[pre[u]]=u;
						}
						return 1;
					}
					v[match[y]]=1;
					q.push(match[y]);
				}
				else
				{
					int w=lca(x,y);
					blossom(x,y,w);blossom(y,x,w);
				}
			}
		}
		return 0;
	}
}
void solve()
{
	cin>>n>>m;
	for(re i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		GP::addedge(x,y);
	}
	int p=0;
	for(re i=1;i<=n;i++)  if(!GP::match[i])  p+=GP::bfs(i);
	printf("%d\n",p);
	for(re i=1;i<=n;i++)  printf("%d ",GP::match[i]);
}
signed main()
{
//	freopen("P1505_1.txt", "r", stdin);
//	freopen("Aout.txt", "w", stdout);
    int T=1;
//    cin>>T;
    for(int index=1;index<=T;index++)
    {
//        printf("Case #%lld: ",index);
        solve();
//        puts("");
    }
    return 0;
}
/*

10 5
hbtngdflmj
1 10 1
2 9 0
3 8 1
4 7 0
5 6 1


*/

标签:花树,pre,get,int,void,算法,奇环,match,define
来源: https://blog.csdn.net/lcl1234567890lcl/article/details/121410046