【UOJ】#79. 一般图最大匹配
题解
板子!我相信其实没人来看我的板子!但是为了防止我忘记,我还是要写点什么
我们考虑二分图,为什么二分图就能那么轻松地写出匹配的代码呢?因为匹配只会发生在黑点和白点之间,我们找寻增广路,必然是一黑一白一黑一白这么走
然而,一般图由于有了奇环,事情变得不妙了啊
奇环上的所有点,可以是……任意的奇偶性(起点到它的距离的奇偶性,可以是非简单路径)
那么我们就让任意奇偶性的点可以进行匹配就可以了,我们通过pre维护出一条路径到达根节点
怎么维护呢?缩花!
花?什么是花?
花就是奇环,我们找到花托(两个点的最近公共祖先),从两个点构建一条能走到花托的路径
如何构建
对于(u,v)和花托f
我们让u的pre走到v,然后令u跳到u匹配点的pre,v变成u的匹配点,继续这个操作,同时把这个匹配点改成偶点(可进行增广)
对v走到花托走到f进行类似的操作
代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define enter putchar('\n')
#define space putchar(' ')
#define MAXN 505
//#define ivorysi
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
struct node {
int to,next;
}E[MAXN * MAXN * 2];
int sumE,head[MAXN];
int N,M,fa[MAXN],pre[MAXN],matk[MAXN],sta[MAXN];
int Q[MAXN],L,R;
void add(int u,int v) {
E[++sumE].to = v;
E[sumE].next = head[u];
head[u] = sumE;
}
int getfa(int x) {
return fa[x] == x ? x : fa[x] = getfa(fa[x]);
}
int lca(int x,int y) {
static int vis[MAXN],Tim;
++Tim;
while(1) {//每个点都尝试走一步
x = getfa(x);
if(x) {
if(vis[x] == Tim) {
return x;
}
else vis[x] = Tim,x = pre[matk[x]];
}
swap(x,y);
}
}
void blossom(int u,int v,int flower_root) {
while(getfa(u) != flower_root) {
pre[u] = v;
//我们每个点既然都是奇偶难分(雾)
//就构建出一条这个点走到花托的交错路
//构建方法就是顺着匹配边往上跳
//这个时候我们碰到的匹配点还都以为自己是偶点= =(奇怪的叙述)
int m = matk[u];
if(sta[m] == 1) {sta[m] = 0;Q[++R] = m;}
//把所有以为自己是奇点的人告诉他们可以当偶点啦
if(u == fa[u]) fa[u] = flower_root;
if(m == fa[m]) fa[m] = flower_root;
v = m,u = pre[m];
}
}
bool match(int s) {
//sta : -1 未访问 0:偶点(起始点) 1:奇点
//pre : 交错树上的父亲,任意一点顺着当前自己的匹配点的pre会走到树根,也就是还原出了交错路
L = 1,R = 0;Q[++R] = s;
memset(sta,-1,sizeof(sta));
memset(pre,0,sizeof(pre));
sta[s] = 0;//起点是偶点
for(int i = 1 ; i <= N ; ++i) fa[i] = i;
while(L <= R) {
int u = Q[L++];
for(int i = head[u] ; i ; i = E[i].next) {
int v = E[i].to;
if(sta[v] == -1) {
pre[v] = u;sta[v] = 1;
if(!matk[v]) {
for(int j = u , k = v,last; ; j = pre[k = last]) {
last = matk[j],matk[j] = k;matk[k] = j;
if(!last) break;
}//顺着pre节点找交错路,全部取反
return 1;
}
sta[matk[v]] = 0;
Q[++R] = matk[v];
}
else if(getfa(v) != getfa(u) && !sta[v]) {
int f = lca(u,v);blossom(u,v,f);blossom(v,u,f);
//两个偶点,缩花,两条路径爬到父亲
}
}
}
return 0;
}
void Init() {
read(N);read(M);
int u,v;
for(int i = 1 ; i <= M ; ++i) {
read(u);read(v);
add(u,v);add(v,u);
}
}
void Solve() {
int ans = 0;
for(int i = 1 ; i <= N ; ++i) {
if(!matk[i] && match(i)) ++ans;
}
out(ans);enter;
for(int i = 1 ; i <= N ; ++i) {
out(matk[i]);
if(i == N) enter;
else space;
}
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}
//5aaC5p6c5oiR5LiK5LiN5LqGdGh177yM5oiR5bCx5YaN5Lmf6KeB5LiN5Yiw54yr6ZSf5LqG
//4oCm4oCm54yr6ZSf55yf5Y+v54ix
【UOJ】#79. 一般图最大匹配的更多相关文章
- UOJ #79 一般图最大匹配 带花树
http://uoj.ac/problem/79 一般图和二分图的区别就是有奇环,带花树是在匈牙利算法的基础上对奇环进行缩点操作,复杂度似乎是O(mn)和匈牙利一样. 具体操作是一个一个点做类似匈牙利 ...
- UOJ #79. 一般图最大匹配
板子: #include<iostream> #include<cstdio> #include<algorithm> #include<vector> ...
- 【刷题】UOJ #79 一般图最大匹配
从前一个和谐的班级,所有人都是搞OI的.有 \(n\) 个是男生,有 \(0\) 个是女生.男生编号分别为 \(1,-,n\) . 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个 ...
- uoj#79. 一般图最大匹配(带花树)
传送门 带花树 不加证明的说一下过程好了:每次从一个未匹配点\(S\)出发bfs,设\(S\)为\(1\)类点,如果当前点\(v\)在本次bfs中未经过,分为以下两种情况 1.\(v\)是未匹配点,那 ...
- 【UOJ#79】一般图最大匹配(带花树)
[UOJ#79]一般图最大匹配(带花树) 题面 UOJ 题解 带花树模板题 关于带花树的详细内容 #include<iostream> #include<cstdio> #in ...
- UOJ79 一般图最大匹配
题目描述 从前一个和谐的班级,所有人都是搞OI的.有 nn 个是男生,有 00 个是女生.男生编号分别为 1,-,n1,-,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人 ...
- [转]带花树,Edmonds's matching algorithm,一般图最大匹配
看了两篇博客,觉得写得不错,便收藏之.. 首先是第一篇,转自某Final牛 带花树……其实这个算法很容易理解,但是实现起来非常奇葩(至少对我而言). 除了wiki和amber的程序我找到的资料看着都不 ...
- HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力
一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...
- 【Learning】带花树——一般图最大匹配
一般图最大匹配--带花树 问题 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. 这个问题的退化版本就是二分图最大匹配. 由于二分图中不存在奇环,偶环对最大匹配并无 ...
随机推荐
- Codeforces 950.E Data Center Maintenance
E. Data Center Maintenance time limit per test 1 second memory limit per test 512 megabytes input st ...
- 使用gulp进行css、js压缩
var gulp = require('gulp'); var cleanCSS = require('gulp-clean-css'); var concatCss = require('gulp- ...
- bzoj 2277 [Poi2011]Strongbox 数论
2277: [Poi2011]Strongbox Time Limit: 60 Sec Memory Limit: 32 MBSubmit: 527 Solved: 231[Submit][Sta ...
- lightoj 1148 Mad Counting(数学水题)
lightoj 1148 Mad Counting 链接:http://lightoj.com/volume_showproblem.php?problem=1148 题意:民意调查,每一名公民都有盟 ...
- discuz更换域名,登录不了解决
准备工作 :因为域名更换了,因此原域名就不能再进后台了,请申请好新域名,并正确备案,让机房添加白名单,重新解析,重新绑定空间..... 完成一系列工作后,进入DZ程序修改. ------------- ...
- ASP.NET 使用ajaxupload.js插件出现上传较大文件失败的解决方法
在网上下载了一个ajaxupload.js插件,用于无刷新上传图片使的,然后就按照demo的例子去运行了一下,上传啊什么的都OK,但是正好上传的示例图片有一个比较大的,4M,5M的样子,然后上传就会报 ...
- Spring websocket浏览器连接时出现404错误
1.场景 在用websocket做一个简单的数据导入页面同步显示后台进度功能的时候,浏览器出现连接不上的错误: WebSocket connection to 'ws://localhost:8080 ...
- 20155117王震宇 2016-2017-2 《Java程序设计》第八周学习总结
教材学习内容总结 正则表达式 正则表达式是记录文本规则的代码 元字符 ^ :^会匹配行或者字符串的起始位置,有时还会匹配整个文档的起始位置. $ :$会匹配行或字符串的结尾. \b :不会消耗任何字符 ...
- layer弹窗的跳转功能
1,本弹窗直接跳转父页面: @if(session('message')) <script> window.parent.location.reload(); //刷新父页面 var in ...
- python 天气爬虫
python3 爬取全国天气信息 制作一个天气查询软件,能够查询全国范围内的天气数据. github:https://github.com/1052687889/weatherApp 基于PyQt5编 ...