带花树裸题,感觉带花树强强……不会的勿看此文,解释的可能不对,只是给自己看的!!!如题,带花树即为求一般图最大匹配算法(匈牙利与dinic为二分图最大匹配)。推荐论文:2015年《浅谈图的匹配算法及其应用》(长郡中学    ——陈胤伯)。论文当中有对于带花树算法的详细解析,在这里只想记录一下算法的基本流程:

——————————————————————————

  \(id\) : 记录一个点为奇点/偶点(0偶1奇)。

  \(fa\) : 并查集记录一个点属于哪一个点为根的花。

——————————————————————————

  我们对于每一个没有匹配到的点进行 bfs,默认该点为一个偶点。

  当我们遍历到一个未访问过的点(在此次bfs中):

    -若该点未匹配:

    Yes!我们找到了一条新的增广路。顺着 \( pre \) 数组的指引反向增广,修改匹配的对象。(当前点为\(x\), \(y = pre[x]\),\(z = match[y]\), 则应使 \(x\), \(y\) 成为匹配边,\(z\) 点继续增广(过程同上,一直到增广不下去了为止))。

    -若该点已匹配:

    将它的匹配点标记为偶点,推进队列。

  遍历到一个访问过的点(在此次bfs中):

    -若该点是一个奇点:

    找到的是一个偶环,无视。

    -若该点是一个偶点:

    如果这两个点本来就在同一朵花中,无视。否则进行缩花。我们找到这两点在bfs树上的 lca: \(k\);将这两点之间连上边从\(x\) 开始向上遍历所有的匹配边,找到一朵花的根节点就修改其花根为 \(k\); 若找到的点有匹配点,则将匹配点也标记为偶点并压入队列。

  总之是个玄学算法……

#include <bits/stdc++.h>
using namespace std;
#define maxn 300000
int n, m, match[maxn];
int pre[maxn], id[maxn];
int timer, fa[maxn], ans;
int vis[maxn];
queue <int> q; struct edge
{
int cnp = , head[maxn], to[maxn], last[maxn];
void add(int u, int v)
{
to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++;
to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++;
}
}E1; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar(); }
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } void Clear(queue<int> &q) {
queue <int> empty;
swap(empty, q);
} int LCA(int x, int y)
{
timer ++;
while(vis[x] != timer)
{
if(x)
{
x = find(x);
if(vis[x] == timer) return x;
vis[x] = timer;
if(match[x]) x = find(pre[match[x]]);
else x = ;
}
swap(x, y);
}
return x;
} void Change(int x, int y, int k)
{
while(find(x) != k)
{
pre[x] = y; int z = match[x];
if(id[z] == ) id[z] = , q.push(z);
if(find(z) == z) fa[z] = k;
if(find(x) == x) fa[x] = k;
y = z; x = pre[y];
}
} bool bfs(int u)
{
for(int i = ; i <= n; i ++) id[i] = -, fa[i] = i;
Clear(q); q.push(u); id[u] = ;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = E1.head[u]; i; i = E1.last[i])
{
int v = E1.to[i];
if(id[v] == -)
{
pre[v] = u; id[v] = ;
if(match[v])
{
id[match[v]] = ; q.push(match[v]);
continue;
}
int last, t, now = v;
while(now)
{
t = pre[now]; last = match[t];
match[t] = now, match[now] = t;
now = last;
}
return ;
}
else if(!id[v] && find(u) != find(v))
{
int lca = LCA(u, v);
Change(u, v, lca), Change(v, u, lca);
}
}
}
return ;
} int main()
{
n = read(), m = read();
for(int i = ; i <= m; i ++)
{
int x = read(), y = read();
E1.add(x, y);
}
for(int i = ; i <= n; i ++) if(!match[i] && bfs(i)) ans ++;
printf("%d\n", ans);
for(int i = ; i <= n; i ++) printf("%d ", match[i]);
return ;
}

【题解】Uoj79一般图最大匹配的更多相关文章

  1. UOJ79 一般图最大匹配

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

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

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

  3. [WC2016]挑战NPC(一般图最大匹配)

    [WC2016]挑战NPC(一般图最大匹配) Luogu 题解时间 思路十分有趣. 考虑一个筐只有不多于一个球才有1的贡献代表什么. 很明显等效于有至少两个位置没有被匹配时有1的贡献. 进而可以构造如 ...

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

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

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

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

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

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

  7. HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】

    <题目链接> 题目大意: 给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的. 解题分析: 所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义.那怎样 ...

  8. ZOJ 3316 Game 一般图最大匹配带花树

    一般图最大匹配带花树: 建图后,计算最大匹配数. 假设有一个联通块不是完美匹配,先手就能够走那个没被匹配到的点.后手不论怎么走,都必定走到一个被匹配的点上.先手就能够顺着这个交错路走下去,最后一定是后 ...

  9. [JZOJ5279]香港记者题解--最短路图

    [JZOJ5279]香港记者题解--最短路图 题目链接 过 于 暴 力 分析 有一个naiive的想法就是从1到n跑最短路,中途建图,然后在图上按字典序最小走一遍,然而·这是不行的,你这样跳不一定能跳 ...

随机推荐

  1. Mac iTem2 自动登录服务器配置

    假设你要连接的服务器地址为123.123.123.123,端口号为8888,用户名为root,密码为mimamima 编写shell文件"login_server.sh",并放置于 ...

  2. Grafana学习

    一.安装 Grafana最新版本4.3.1安装(后端使用mysql) 二.使用

  3. 了解和分析iOS Crash

    WeTest 导读 北京时间凌晨一点,苹果一年一度的发布会如期而至.新机型的发布又会让适配相关的同学忙上一阵子啦,并且iOS Crash的问题始终伴随着移动开发者.本文将从三个阶段,由浅入深的介绍如何 ...

  4. Python中assert的作用?

    1. assert 的作用是什么? assert这个关键字我们称之为“断言”,当这个关键字后边的条件为假的时候,程序自动崩溃并抛出AssertionError的异常. 什么情况下我们会需要这样的代码呢 ...

  5. 167. Add Two Numbers【LintCode by java】

    Description You have two numbers represented by a linked list, where each node contains a single dig ...

  6. 使用flume抓取tomcat的日志文件下沉到kafka消费

    Tomcat生产日志 Flume抓取日志下沉到kafka中 将写好的web项目打包成war包,eclise直接导出export,IDEA 在artifact中添加新的artifact-achieve项 ...

  7. 1053 Path of Equal Weight (30 分)(树的遍历)

    题目大意:给出树的结构和权值,找从根结点到叶子结点的路径上的权值相加之和等于给定目标数的路径,并且从大到小输出路径 #include<bits/stdc++.h> using namesp ...

  8. jupyter notebook 使用cmd命令窗口打开

    第一步:将文件路径改为你需要使用文件所在的路径 第二部:   jupyter notebook

  9. opencv-学习笔记(5)形态学转变

    opencv-学习笔记(4)形态学转变 本章讲了几种形态学操作 腐蚀erode 膨胀dilate 开运算MORPH_OPEN 闭运算MORPH_CLOSE 形态学梯度MORPH_GRADIENT 礼帽 ...

  10. 2018-8-29安装Jitamin过程实录

    2018-8-29安装Jitamin过程实录 新建 模板 小书匠 欢迎走进zozo的学习之旅. 简介 安装 nginx + php + mysql 安装composer 安装Jitamin 简介 在考 ...