题解

板子!我相信其实没人来看我的板子!但是为了防止我忘记,我还是要写点什么

我们考虑二分图,为什么二分图就能那么轻松地写出匹配的代码呢?因为匹配只会发生在黑点和白点之间,我们找寻增广路,必然是一黑一白一黑一白这么走

然而,一般图由于有了奇环,事情变得不妙了啊

奇环上的所有点,可以是……任意的奇偶性(起点到它的距离的奇偶性,可以是非简单路径)

那么我们就让任意奇偶性的点可以进行匹配就可以了,我们通过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. 一般图最大匹配的更多相关文章

  1. UOJ #79 一般图最大匹配 带花树

    http://uoj.ac/problem/79 一般图和二分图的区别就是有奇环,带花树是在匈牙利算法的基础上对奇环进行缩点操作,复杂度似乎是O(mn)和匈牙利一样. 具体操作是一个一个点做类似匈牙利 ...

  2. UOJ #79. 一般图最大匹配

    板子: #include<iostream> #include<cstdio> #include<algorithm> #include<vector> ...

  3. 【刷题】UOJ #79 一般图最大匹配

    从前一个和谐的班级,所有人都是搞OI的.有 \(n\) 个是男生,有 \(0\) 个是女生.男生编号分别为 \(1,-,n\) . 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个 ...

  4. uoj#79. 一般图最大匹配(带花树)

    传送门 带花树 不加证明的说一下过程好了:每次从一个未匹配点\(S\)出发bfs,设\(S\)为\(1\)类点,如果当前点\(v\)在本次bfs中未经过,分为以下两种情况 1.\(v\)是未匹配点,那 ...

  5. 【UOJ#79】一般图最大匹配(带花树)

    [UOJ#79]一般图最大匹配(带花树) 题面 UOJ 题解 带花树模板题 关于带花树的详细内容 #include<iostream> #include<cstdio> #in ...

  6. UOJ79 一般图最大匹配

    题目描述 从前一个和谐的班级,所有人都是搞OI的.有 nn 个是男生,有 00 个是女生.男生编号分别为 1,-,n1,-,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人 ...

  7. [转]带花树,Edmonds's matching algorithm,一般图最大匹配

    看了两篇博客,觉得写得不错,便收藏之.. 首先是第一篇,转自某Final牛 带花树……其实这个算法很容易理解,但是实现起来非常奇葩(至少对我而言). 除了wiki和amber的程序我找到的资料看着都不 ...

  8. HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力

    一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...

  9. 【Learning】带花树——一般图最大匹配

    一般图最大匹配--带花树 问题 ​ 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. ​ 这个问题的退化版本就是二分图最大匹配. ​ 由于二分图中不存在奇环,偶环对最大匹配并无 ...

随机推荐

  1. 洛谷P2617 Dynamic Rankings (主席树)

    洛谷P2617 Dynamic Rankings 题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a ...

  2. get与post请求简单理解

    一般在浏览器中输入网址访问资源都是通过GET方式:在FORM提交中,可以通过Method指定提交方式为GET或者POST,默认为GET提交 Http定义了与服务器交互的不同方法,最基本的方法有4种,分 ...

  3. wordpress初始化安装

    数据名,用户名,密码的选择: 从主机购买商的控制面板里面查询: 然后填入到WordPress数据库初始化页面..

  4. bzoj 1070 费用流

    //可以网络流,但是要怎么分配每辆车让谁维修以及维修顺序呢.可以考虑每辆车维修时间对总结果的贡献,把每个修车人拆成n个点共n*m个点, //n辆车连向这n*m个点,流量1,费用k*修车时间,其中k(1 ...

  5. bzoj 1879 状压dp

    879: [Sdoi2009]Bill的挑战 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 852  Solved: 435[Submit][Status ...

  6. pasty公式

    sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  7. echarts 分组绘制柱状图

    示意图: 代码如下: <!DOCTYPE html> <html style="height: 100%"> <head> <meta c ...

  8. Tensorboard教程:高维向量可视化

    Tensorflow高维向量可视化 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 强烈推荐Tensorflow实战Google深度学习框架 实验平台: Tensorflow1.4. ...

  9. python---Scrapy模块的使用(一)

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中. Scrapy 使用了 Twisted异步网络库来处理网络通讯.整体 ...

  10. hadoop之安全篇

    ---------------持续更新中------------------- hadoop集群安全架构 如下图所示: --------------------------未完待续---------- ...