【图论】一般图最大匹配
题目描述
给出一张
算法概述
带花树算法,在基于 bfs 版本的匈牙利上改造。考虑一般的二分图,它的特征是出现环的情况下只有偶环。然而一般的图里面可能有奇环,找匹配点不只可以找同侧点,所以不能用匈牙利。
我们将一个图二分图染色,如果是黑色,就找白色或者未染色出边,匹配那个点,然后将那个点的
注意队列里只有黑点,没有白点。
这里,我们只需要考虑黑点向黑点连边的情况,我们发现现在连成了一个奇环。环上一定是
考虑并查集完成这一过程,首先找到两个点在搜索路径上的
至于去找这个花根,从两个点开始交错向上跳,跳过的黑点打标记,如果跳到了一个标记相同的点,一定是花根。
然后如果找到了没匹配的点的话,就直接通过
这个算法主要麻烦的一点就是连边不是单纯的通过
时间复杂度和匈牙利一样,是
Code
#include<bits/stdc++.h>
using namespace std;
const int N = 1005,M = 5e4 + 5;
struct Edge{
int v,next;
}e[M * 2];
int vis[N],match[N],mark[N],head[N],pre[N],n,m,tot = 0;
inline void add(int x,int y)
{
++tot;
e[tot].v = y;
e[tot].next = head[x];
head[x] = tot;
}
queue <int> q;
int fa[N];
inline int find(int x)
{
if(x == fa[x]) return x;
return find(fa[x]);
}
inline int getlca(int x,int y)
{
++tot;
x = find(x); y = find(y);
while(mark[x] != tot)
{
mark[x] = tot;
x = find(pre[match[x]]);
if(y) swap(x,y);
}
return x;
}
inline void blossom(int x,int y,int z)
{
while(find(x) != z)
{
pre[x] = y;
y = match[x];
if(vis[y] != 1) vis[y] = 1,q.push(y);
if(find(x) == x) fa[x] = z;
if(find(y) == y) fa[y] = z;
x = pre[y];
}
}
inline bool try_match(int st)
{
for(int i = 1;i <= n;i++) fa[i] = i;
memset(vis,0,sizeof(vis)); memset(pre,0,sizeof(pre));
while(!q.empty()) q.pop();
q.push(st);
vis[st] = 1;
while(!q.empty())
{
int x = q.front(); q.pop();
for(int i = head[x];i;i = e[i].next)
{
int to = e[i].v;
if(find(x) == find(to)) continue; // in the same flower
if(vis[to] == 2) continue; //even circle
if(!vis[to])
{
pre[to] = x; vis[to] = 2;
if(!match[to])
{
for(int j = to,k;j;j = k)
{
k = match[pre[j]];
match[j] = pre[j];
match[pre[j]] = j;
}
return true;
}
else q.push(match[to]),vis[match[to]] = 1;
}
else
{
int z = getlca(x,to);
blossom(x,to,z);
blossom(to,x,z);
}
}
}
return 0;
}
int main()
{
cin>>n>>m;
for(int i = 1,x,y;i <= m;i++) cin>>x>>y,add(x,y),add(y,x);
int ans = 0; tot = 0;
for(int i = 1;i <= n;i++) if(!match[i]) ans += try_match(i);
cout<<ans<<endl;
for(int i = 1;i <= n;i++) cout<<match[i]<<" ";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通