Toptree初探

一般图最大匹配,带花树算法

RXDoi posted @ 2016年2月12日 18:51 in 笔记 , 235 阅读

暂时先学个一般图最大匹配的吧……权匹配好像有点复杂。

p.s. WC至今只补了1题,跪早已补完的某老司机。


http://www.csie.ntnu.edu.tw/~u91029/Matching.html

这篇讲得非常好。

就是搞清楚奇点有pre,偶点才会进队。缩花之后修改偶点的pre,把奇点改成偶点进队。

#include<set>
#include<map>
#include<cmath>
#include<string>
#include<cstdio>
#include<vector>
#include<cctype>
#include<cstdlib>
#include<sstream>
#include<cstring>
#include<iostream>
#include<algorithm>

#define For(i,x,y) for (int i=x;i<y;i++)
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
using namespace std;

int IN()
{
	int c,f,x;
	while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
	while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
}

typedef long long ll;
typedef double Db;
typedef pair<int,int> pii;

const int N=500+19,M=124750+19;
typedef int one[N];
struct Edge {int y,nxt;} E[M*2];
one Last,Q,mate,col,pre,fa,vis;
int n,m,cnt,f,w,Time,x,y,Ans;

int getf(int x) {return fa[x]==x?x:fa[x]=getf(fa[x]);}
void Link(int x,int y)
{
	E[cnt]=(Edge){y,Last[x]};Last[x]=cnt++;
	E[cnt]=(Edge){x,Last[y]};Last[y]=cnt++;
}

int LCA(int x,int y)
{
	Time++;
	for (;;swap(x,y))
		if (x=getf(x))
		{
			if (vis[x]==Time) return x;
			vis[x]=Time,x=pre[mate[x]];
		}
}
void blossom(int u,int v)
{
	for (int x,y;u!=v;u=y)
	{
		x=mate[u],y=pre[x];
		if (getf(y)!=v) pre[y]=x;
		if (col[x]==1) col[Q[++f]=x]=0;
		fa[getf(u)]=getf(x);
		fa[getf(x)]=getf(y);
	}
}
int Find(int S)
{
	memset(col,-1,sizeof(col));
	memset(pre,0,sizeof(pre));
	For(i,1,n+1) fa[i]=i;
	f=1,w=0;Q[1]=S;col[S]=0;
	while (f>w)
	{
		int x=Q[++w];
		for (int i=Last[x],y;~i;i=E[i].nxt)
		{
			y=E[i].y;
			if (getf(x)==getf(y)||y==mate[x]||col[y]==1) continue;
			if (col[y]==-1)
			{
				if (mate[y])
				{
					pre[y]=x;
					col[y]=1;
					col[Q[++f]=mate[y]]=0;
				} else
				{
					for (int z;x;y=z,x=pre[z]) z=mate[x],mate[x]=y,mate[y]=x;
					return 1;
				}
			} else if (col[y]==0)
			{
				int z=LCA(x,y);
				if (getf(x)!=z) pre[x]=y;
				if (getf(y)!=z) pre[y]=x;
				blossom(x,z);
				blossom(y,z);
			}
		}
	}
	return 0;
}

int main()
{
	memset(Last,-1,sizeof(Last));
	n=IN(),m=IN();
	For(i,0,m)
	{
		x=IN(),y=IN(),Link(x,y);
		if (!mate[x]&&!mate[y]) mate[x]=y,mate[y]=x,Ans++;
	}
	For(i,1,n+1) if (!mate[i]&&Find(i)) Ans++;
	printf("%d\n",Ans);
	For(i,1,n+1) printf("%d ",mate[i]);puts("");
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter