一般图最大匹配(奇环处理) 带花树算法
作者:互联网
匈牙利算法最大的问题在于无法处理带奇环的图,如果存在奇环,那么程序会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