UOJ #79 一般图最大匹配 带花树
一般图和二分图的区别就是有奇环,带花树是在匈牙利算法的基础上对奇环进行缩点操作,复杂度似乎是O(mn)和匈牙利一样。
具体操作是一个一个点做类似匈牙利的找增广路操作,每次将一个点作为根(染成白色),然后向下bfs黑白染色,两个白点相邻时将这两个白点缩到割顶成一个点(用并查集维护一下)(匈牙利算法也是只用白点找增广,黑点相当于重复计算了没有意义),然后把奇环里所有黑点视为白点放到队列里bfs。
设置一个pre数组记录返回的路径(因为bfs的方向和匈牙利是相反的所以最后找到的时候再顺着返回的路径重新匹配),因为重新匹配的时候找的是可匹配的黑点,所以在dfs的时候只用给每个黑点设置pre,产生奇环的时候再对白点设置pre,因为此时奇环里的点匹配之后才能决定颜色(黑白都可以)。
这个算法,有一丶丶恶心。
原理详解:https://blog.csdn.net/u014261987/article/details/41249385
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
#define LL long long
const int maxn=;
const int mmm=;
int n,m;
struct nod{
int y,next;
}e[maxn];
int head[mmm]={},q[maxn]={},tl=,tr=,tot=;
int fa[mmm]={},tp[mmm]={},pre[mmm]={},d[mmm]={},bel[mmm]={},tly=;
void init(int x,int y){e[++tot].y=y;e[tot].next=head[x];head[x]=tot;}
inline int getfa(int x){
return fa[x]==x?x:fa[x]=getfa(fa[x]);
}
inline int lca(int x,int y){
++tly;
for(;;){
if(x){
x=getfa(x);
if(bel[x]==tly)return x;
else {bel[x]=tly;x=pre[d[x]];}
}
swap(x,y);
}
}
inline void mlink(int x,int y,int pa){
while(getfa(x)!=pa){
pre[x]=y;y=d[x];
if(tp[y]==){tp[y]=;q[++tr]=y;}
if(getfa(x)==x)fa[x]=pa;
if(getfa(y)==y)fa[y]=pa;
x=pre[y];
}
}
int doit(int s){
for(int i=;i<=n;++i)fa[i]=i;
memset(tp,,sizeof(tp));memset(pre,,sizeof(pre));
tl=tr=;q[]=s;tp[s]=;
while(tl<=tr){
int x=q[tl];++tl;
for(int i=head[x];i;i=e[i].next){
int y=e[i].y;
if(getfa(x)==getfa(y)||tp[y]==)continue;
if(!tp[y]){
tp[y]=;pre[y]=x;
if(!d[y]){
for(int now=y,las,j;now;now=las){
j=pre[now]; las=d[pre[now]];
d[now]=j;d[j]=now;
}
return ;
}
tp[d[y]]=;q[++tr]=d[y];
}
else{
int pa=lca(x,y);
mlink(x,y,pa);mlink(y,x,pa);
}
}
}return ;
}
int main(){
scanf("%d%d",&n,&m);
int x,y;
for(int i=;i<m;++i){scanf("%d%d",&x,&y);init(x,y);init(y,x);}
int ans=;
for(int i=;i<n;++i){if(!d[i])ans+=doit(i);}
printf("%d\n",ans);
for(int i=;i<=n;++i)if(d[i])d[d[i]]=i;
for(int i=;i<=n;++i){
printf("%d ",d[i]);
}printf("\n");
return ;
}
UOJ #79 一般图最大匹配 带花树的更多相关文章
- HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力
一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...
- ZOJ 3316 Game 一般图最大匹配带花树
一般图最大匹配带花树: 建图后,计算最大匹配数. 假设有一个联通块不是完美匹配,先手就能够走那个没被匹配到的点.后手不论怎么走,都必定走到一个被匹配的点上.先手就能够顺着这个交错路走下去,最后一定是后 ...
- 【UOJ #79】一般图最大匹配 带花树模板
http://uoj.ac/problem/79 带花树模板,做法详见cyb的论文或fhq的博客. 带花树每次对一个未盖点bfs增广,遇到奇环就用并查集缩环变成花(一个点),同时记录每个点的Next( ...
- 【UOJ 79】 一般图最大匹配 (✿带花树开花)
从前一个和谐的班级,所有人都是搞OI的.有 n 个是男生,有 0 个是女生.男生编号分别为 1,…,n. 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个人负责吐槽.每个人至多属于 ...
- uoj#79. 一般图最大匹配(带花树)
传送门 带花树 不加证明的说一下过程好了:每次从一个未匹配点\(S\)出发bfs,设\(S\)为\(1\)类点,如果当前点\(v\)在本次bfs中未经过,分为以下两种情况 1.\(v\)是未匹配点,那 ...
- 【learning】一般图最大匹配——带花树
问题描述 对于一个图\(G(V,E)\),当点对集\(S\)满足任意\((u,v)\in S\),均有\(u,v\in V,(u,v)\in E\),且\(S\)中没有点重复出现,我们称\(S\) ...
- 【刷题】UOJ #79 一般图最大匹配
从前一个和谐的班级,所有人都是搞OI的.有 \(n\) 个是男生,有 \(0\) 个是女生.男生编号分别为 \(1,-,n\) . 现在老师想把他们分成若干个两人小组写动态仙人掌,一个人负责搬砖另一个 ...
- UOJ #79. 一般图最大匹配
板子: #include<iostream> #include<cstdio> #include<algorithm> #include<vector> ...
- kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树
二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j ...
随机推荐
- Mysql被攻击
日志: show global variables like '%general%'; set global general_log=on; 默认Path:/var/run/mysqld/mysqld ...
- 使用python命令构建最简单的web服务
可以使用python自带的包建立最简单的web服务器,使用方法: 1)切换到服务器的根目录下 2)输入命令: python -m SimpleHTTPServer 3)使用wget或者在浏览器访问测试 ...
- 【前端】三个bug
目录 一.Array对象的indexOf() 二.使用jquery,clone()下拉框问题 三.jquery获取获取html5的data-*属性 一.Array对象的indexOf() 1.inde ...
- vue-cli 搭建的项目处理不同环境下请求不同域名的问题
使用 vue-cli 开发项目过程中, 根据开发环境和正式环境不同, 我们往往需要请求不同域名下的后台接口, 这时候, 该怎么去设置, 达到同一种写法可以根据环境不同而自动切换请求域名呢? 本文将会介 ...
- ssh-keygen -t rsa -b 4096 -C "邮箱"
ssh-keygen -t rsa -b 4096 -C "邮箱":这条命令的目的是为了让本地机器ssh登录远程机器上的GitHub账户无需输入密码.将这条命令分解: 1.ssh- ...
- SpringBoot入门小案例
1.创建一个简单的maven project项目 2.下面来看一下项目结构: 3.pom.xml 配置jar包 <parent> <groupId>org.springfram ...
- LeetCode(4):两个排序数组的中位数
Hard! 题目描述: 有两个大小为 m 和 n 的排序数组 nums1 和 nums2 . 请找出两个排序数组的中位数并且总的运行时间复杂度为 O(log (m+n)) . 示例 1: nums1 ...
- PHP获取文件后缀名
PHP获取文件后缀名是PHP学习者常见的一种操作,无论是在面试过程中还是PHP新手自学中.PHP获取文件后缀名都是很普遍的需要掌握的一个知识点. 下面我们就给大家总结介绍PHP获取文件扩展名也就是后缀 ...
- python调用修改变量新方法
def foo(): count = [1] #将变量放在列表中,此时,内部函数就可以修改了 def bar(): count[0] = count[0] + 1 return count[0] re ...
- hdu2642二维树状数组单点更新
碰到这种题一定要注意坐标是不是有序的,也要注意坐标是不是有0的,有的话需要+1处理 #include<bits/stdc++.h> using namespace std; #define ...