【模板】一般图最大匹配(带花树算法)/洛谷P6113
2024-08-30 05:22:07
题目链接
https://www.luogu.com.cn/problem/P6113
题目大意
给定一个 \(n\) 个点 \(m\) 条边的无向图,求该图的最大匹配。
题目解析
二分图最大匹配,一般用匈牙利算法完成,图中只存在偶环。
而一般图不能分为左右两部,存在奇环,如何处理奇环,是带花树算法的关键。
若将偶环缩为一点,则该图可以简化为只有奇环的无向图。
对于奇环内部,两两匹配后必定多出一个点不能匹配,则将该点与环外部的点相匹配即可。
通过类似匈牙利算法的多次增广,可以找到最大匹配。
点数为 \(n\),边数为 \(m\) 。
时间复杂度: \(O(n^2 m)\)
参考代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1005;
int n, m, cnt;
int fa[N], vis[N], tag[N], pre[N], match[N];
queue <int> q;
vector <int> e;
vector <int> G[N];
void addEdge(int a, int b, int i)
{
e.push_back(b);
e.push_back(a);
G[a].push_back(i);
G[b].push_back(i ^ 1);
}
inline int find(int x) {return fa[x] == x ? x : fa[x] = find(fa[x]);}
inline int lca(int x, int y)
{
++cnt;
while (true)
{
if (x)
{
x = find(x);
if (tag[x] == cnt) return x;
tag[x] = cnt;
x = pre[match[x]];
}
swap(x, y);
}
}
inline void blossom(int x, int y, int p)
{
while (find(x) != p)
{
pre[x] = y; y = match[x];
vis[y] = 1; q.push(y);
if (find(x) == x) fa[x] = p;
if (find(y) == y) fa[y] = p;
x = pre[y];
}
}
bool bfs(int s)
{
for (int i = 1; i <= n; ++i) vis[i] = pre[i] = 0, fa[i] = i;
while (!q.empty()) q.pop();
q.push(s);
vis[s] = 1;
while (!q.empty())
{
int u = q.front(); q.pop();
for (int i = 0; i < G[u].size(); ++i)
{
int v = e[G[u][i]];
if (vis[v] == 2 || find(u) == find(v)) continue;
if (!vis[v])
{
vis[v] = 2, pre[v] = u;
if (!match[v])
{
int x = v;
while (x)
{
int y = pre[x], z = match[y];
match[x] = y, match[y] = x;
x = z;
}
return 1;
}
vis[match[v]] = 1;
q.push(match[v]);
}
else
{
int p = lca(u, v);
blossom(u, v, p);
blossom(v, u, p);
}
}
}
return 0;
}
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < m; ++i) {
int a, b;
scanf("%d%d", &a, &b);
addEdge(a, b, i << 1);
}
int ans = 0;
for (int i = 1; i <= n; ++i) if (!match[i] && bfs(i)) ans++;
printf("%d\n", ans);
for (int i = 1; i <= n; i++) printf("%d%c", match[i], i == n ? '\n' : ' ');
return 0;
}
感谢支持!
最新文章
- c++ 一些随笔
- js注册验证提示!
- spring mvc各种常见类型参数绑定方式以及json字符串绑定对象
- wordpress编辑主题时报错Warning: scandir() has been disabled for security reasons in
- loadrunner具体实例教你如何进行结果分析
- 在Windows7上安装coreseek3.2同时在PHP下简单实现步骤
- IOS开发小项目—找色块游戏
- js案例_下滑列表
- Xcode5.1离线下载安装及使用iOS5模拟器进行开发调试的方法
- Spring MVC 中的 forward 和 redirect
- HTML5-36d嗨起^_^
- 探索 Windows Azure 网站中的自动伸缩功能
- poj 1144 Network(割点)
- 移动端H5页面遇到的问题总结
- java面试集锦
- 代理模式(Proxy)
- Python使用Tabula提取PDF表格数据
- 利用nginx 虚拟主机、请求转发实现不同端口web访问
- Session小结
- Python开发网站目录扫描器
热门文章
- 【SDOI2014】数数(补)
- Navicat15 For Mysql最新版完美破解图文教程(支持Win和Mac)
- 记录一次因subprocess PIPE 引起的线上故障
- 【java+selenium3】自动化截图 (十四)
- Flink 实践教程 - 入门(4):读取 MySQL 数据写入到 ES
- rabbitMQ报错:Caused by: com.rabbitmq.client.ShutdownSignalException: connection error; protocol method:
- Dao、Controller、Service三层的结构划分
- 痞子衡嵌入式:在IAR开发环境下RT-Thread工程函数重定向失效分析
- Linux系统查看磁盘可用空间的5个命令
- Spring中常用注解