带花树(一般图最大匹配)(lzz)

“缩花”的思想虽然易懂,但与具体实现严重不符,其实根本没有“缩”的过程。建议用“增广路树+树上并查集维护信息”理解更直观

#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int N=1010;
int graph[N][N];
int n,m;
int match[N];
int fa[N];
int type[N];
int pre[N];
queue <int> q;


void swap(int &a,int &b)
{
	int k=a; a=b; b=k;
}
int find(int x)
{
	int k=x,i;
	while(fa[k]!=k)k=fa[k];
	while(fa[x]!=k)
	{
		i=fa[x]; fa[x]=k; x=i;
	}
	return k;
}

int vis[N],cnt=0;
int lca(int a,int b)
{
	int k,i,j;
	cnt++;
	a=find(a); b=find(b);
	while(vis[a]!=cnt)
	{
		vis[a]=cnt;
		a=find(pre[match[a]]);
		if(b)swap(a,b);
	}
	return a;
}
void shrink(int x,int root)
{
	int k,i,j;
	x=find(x);
	while(x!=root)
	{
		k=pre[match[x]];
		type[match[x]]=1;
		q.push(match[x]);
		if(find(k)!=root)pre[k]=match[x];
		fa[x]=root; fa[find(match[x])]=root;
		x=find(k);
	}
	return;
}
void bfs(int x)
{
	int k,i,j;
	int a,b,c;
	for(k=1;k<=n;k++)type[k]=vis[k]=pre[k]=0;
	for(k=1;k<=n;k++)fa[k]=k;
	type[x]=1; pre[x]=0;
	while(!q.empty())q.pop();
	q.push(x);
	while(!q.empty())
	{
		a=q.front(); q.pop();
		for(k=1;k<=n;k++)
		{
			
			if(!graph[a][k])continue;
			if(!type[k])
			{
				if(!match[k])
				{
					pre[k]=a;
					while(k)
					{
						i=match[pre[k]];
						match[k]=pre[k]; match[pre[k]]=k;
						k=i;
					}
					return;
				}
				type[k]=2;
				type[match[k]]=1;
				pre[k]=a;
				q.push(match[k]); 
			}
			else if(type[k]==1 && find(a)!=find(k))
			{
				b=k;
				c=lca(a,b);
				if(find(a)!=c)pre[a]=b;
				if(find(b)!=c)pre[b]=a;
				shrink(a,c);
				shrink(b,c);
			}
			
		}
	}
	return;
}
void blossom()
{
	int k,i,j;
	memset(match,0,sizeof(match));
	for(k=1;k<=n;k++)
	{
		if(!match[k])bfs(k);
	}
	return;
}
int main()
{
	int k,i,j;
	int a,b,c;
	int sum=0;
	memset(graph,0,sizeof(graph));
	scanf("%d%d",&n,&m);
	for(k=0;k<m;k++)
	{
		scanf("%d%d",&a,&b);
		graph[a][b]=graph[b][a]=1;
	}
	blossom();
	
	for(k=1;k<=n;k++)if(match[k])sum++;
	printf("%d\n",sum/2);
	for(k=1;k<=n;k++)printf("%d ",match[k]);
	printf("\n");
	
	return 0;
} 
posted @ 2022-03-09 10:45  wild_chicken  阅读(16)  评论(0)    收藏  举报