带花树就是说一个非二分图,图中带有奇环的图,我们不能在奇环中找增广路,因为会陷入死循环,我们可以将带花树的花(奇环)部分缩成点处理,剩下的图就是一个无奇环的图。我们再找增广路,而奇环中的的点我们可以随意分配,但是说起来简单,但是实现很难。经过前人的探索,还有这篇《Efficient Algorithms for Finding Maximal Matching in Graphs》论文,呃,然后后人就写出来模板,这就是一个模板题。

模板:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
const int N = 250;
// 并查集维护
int belong[N];
int findb(int x) {return belong[x] == x ? x : belong[x] = findb(belong[x]);
}
void unit(int a, int b) {a = findb(a);b = findb(b);if (a != b) belong[a] = b;
}int n, match[N];
vector<int> e[N];
int Q[N], rear;
int _next[N], mark[N], vis[N];
// 朴素算法求某阶段中搜索树上两点x, y的最近公共祖先r
int LCA(int x, int y) {static int t = 0; t++;while (true) {if (x != -1) {x = findb(x); // 点要对应到对应的花上去  if (vis[x] == t)return x;vis[x] = t;if (match[x] != -1)x = _next[match[x]];else x = -1;}swap(x, y);}
}void group(int a, int p) {while (a != p) {int b = match[a], c = _next[b];// _next数组是用来标记花朵中的路径的,综合match数组来用,实际上形成了  // 双向链表,如(x, y)是匹配的,_next[x]和_next[y]就可以指两个方向了。  if (findb(c) != p) _next[c] = b;// 奇环中的点都有机会向环外找到匹配,所以都要标记成S型点加到队列中去,  // 因环内的匹配数已饱和,因此这些点最多只允许匹配成功一个点,在aug中  // 每次匹配到一个点就break终止了当前阶段的搜索,并且下阶段的标记是重  // 新来过的,这样做就是为了保证这一点。  if (mark[b] == 2) mark[Q[rear++] = b] = 1;if (mark[c] == 2) mark[Q[rear++] = c] = 1;unit(a, b); unit(b, c);a = c;}
}// 增广
void aug(int s) {for (int i = 0; i < n; i++) // 每个阶段都要重新标记  _next[i] = -1, belong[i] = i, mark[i] = 0, vis[i] = -1;mark[s] = 1;Q[0] = s; rear = 1;for (int front = 0; match[s] == -1 && front < rear; front++) {int x = Q[front]; // 队列Q中的点都是S型的  for (int i = 0; i < (int)e[x].size(); i++) {int y = e[x][i];if (match[x] == y) continue; // x与y已匹配,忽略  if (findb(x) == findb(y)) continue; // x与y同在一朵花,忽略  if (mark[y] == 2) continue; // y是T型点,忽略  if (mark[y] == 1) { // y是S型点,奇环缩点  int r = LCA(x, y); // r为从i和j到s的路径上的第一个公共节点  if (findb(x) != r) _next[x] = y; // r和x不在同一个花朵,_next标记花朵内路径  if (findb(y) != r) _next[y] = x; // r和y不在同一个花朵,_next标记花朵内路径  // 将整个r -- x - y --- r的奇环缩成点,r作为这个环的标记节点,相当于论文中的超级节点  group(x, r); // 缩路径r --- x为点  group(y, r); // 缩路径r --- y为点  }else if (match[y] == -1) { // y自由,可以增广,R12规则处理  _next[y] = x;for (int u = y; u != -1; ) { // 交叉链取反  int v = _next[u];int mv = match[v];match[v] = u, match[u] = v;u = mv;}break; // 搜索成功,退出循环将进入下一阶段  }else { // 当前搜索的交叉链+y+match[y]形成新的交叉链,将match[y]加入队列作为待搜节点  _next[y] = x;mark[Q[rear++] = match[y]] = 1; // match[y]也是S型的  mark[y] = 2; // y标记成T型  }}}
}bool g[N][N];
int main() {scanf("%d", &n);for (int i = 0; i < n; i++)for (int j = 0; j < n; j++) g[i][j] = false;// 建图,双向边  int x, y; while (scanf("%d%d", &x, &y) != EOF) {x--, y--;if (x != y && !g[x][y])e[x].push_back(y), e[y].push_back(x);g[x][y] = g[y][x] = true;}// 增广匹配  for (int i = 0; i < n; i++) match[i] = -1;for (int i = 0; i < n; i++) if (match[i] == -1) aug(i);// 输出答案  int tot = 0;for (int i = 0; i < n; i++) if (match[i] != -1) tot++;printf("%d\n", tot);for (int i = 0; i < n; i++) if (match[i] > i)printf("%d %d\n", i + 1, match[i] + 1);return 0;
}

图论--一般带花树匹配相关推荐

  1. 图论--一般图带花树匹配--模板

    #include <cstdio> #include <cstring> #include <iostream> #include <queue> us ...

  2. 图论 —— 带花树算法

    [概述] 带花树算法用于解决一般图的最大匹配问题. 对于一个图 G(V,E),他的匹配 M 是二元组 (u,v) 组成的集合,其中 u,v∈V,(u,b)∈E,且 M 中不存在重复的点,当 |M| 最 ...

  3. Boke and Tsukkomi——一般图匹配+带花树算法

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4687 A new season of Touhou M-1 Grand Prix is approach ...

  4. luogu P4258 [WC2016]挑战NPC(一般图的最大匹配,带花树,建图、拆点技巧)

    整理的算法模板合集: ACM模板 luogu P4258 [WC2016]挑战NPC 如果是一堆球一堆筐,每一个筐里只能放一个球,求最大能放多少个球, 那么就是一个二分图的最大匹配问题,非常简单,我们 ...

  5. 模板 - 一般图最大匹配(带花树)

    整理的算法模板合集: ACM模板 目录 题目描述 给出一张 n 个点 m 条边的无向图,求该图的最大匹配. 总结一下带花树算法的流程 1.每次找一个未匹配的点出来增广 2.在增广过程中,如果相邻点是白 ...

  6. luogu P6113 【模板】一般图最大匹配(带花树)

    整理的算法模板合集: ACM模板 总结一下带花树算法的流程 1.每次找一个未匹配的点出来增广 2.在增广过程中,如果相邻点是白点,或者是同一朵花中的节点,则直接跳过这个点 3.如果相邻点是一个未被匹配 ...

  7. WC前的颓废——带花树

    QAQ现在很不想写题解博客那就来写个算法吧QAQ... 带花树 题目 来看个题... UOJ79. 某机房里有\(n\)个OIer,其中有\(n\)个男生,\(0\)个女生.现在他们要两两配对. 有\ ...

  8. 【BZOJ4405】【WC2016】挑战NPC(带花树)

    [BZOJ4405][WC2016]挑战NPC(带花树) 题面 BZOJ 洛谷 Uoj Description 小N最近在研究NP完全问题,小O看小N研究得热火朝天,便给他出了一道这样的题目: 有n个 ...

  9. 【学习小记】一般图最大匹配——带花树算法

    Text 一般图的最大匹配仍然是基于寻找增广路的 增广路的定义是这样的一条路径,它不经过重复的点,并且路径两端均没有匹配,且整条路径是非匹配边-匹配边-非匹配边这样交错的. 类比二分图最大匹配的增广路 ...

最新文章

  1. LeetCode 23合并K个升序链表24两两交换链表中的节点
  2. vue弹出层滑动禁止背景跟着滑动_vue移动端弹起蒙层滑动禁止底部滑动操作
  3. OpenCart 2.x 系统商品数量库存减少逻辑
  4. css如何调用函数,从CSS调用JavaScript函数
  5. Python 文件路径
  6. 投屏电视显示服务器拒绝,投屏投不上去怎么办?投屏方法汇总,总有一种适合你!...
  7. 程序猿郭小喵曾经的实习故事
  8. h5支付不能打开支付宝 ios_iOS解决H5支付跳转到支付App及返回原App问题
  9. css3 打车软件等车动画,简单一个渐变放大消失水波加载动画
  10. 基于Transformers库的BERT模型:一个文本情感分类的实例解析
  11. Java 二十三种设计模式
  12. C语言编写九九乘法表,实现不同三角形形状表格输出
  13. 腾达tenda U9无线网卡
  14. 跟上司、领导说话的技巧
  15. 概念区别 【编译型语言与解释型语言、动态类型语言与静态类型语言、强类型语言与弱类型语言】
  16. 大中型规模灵活定制的网吧组网方案(转)
  17. Spring Data JPA 原理与实战第十一天 Session相关、CompletableFuture、LazyInitializationException
  18. uniapp 联级选择器uni-data-picker
  19. 宏杰文件夹加密V2878【永久免费的文件加密软件】
  20. 上次的问题已经得到解决

热门文章

  1. Ajax POST请求获取后台返回的数据
  2. iOS App 目录结构
  3. 禅道 11.4.1 版本发布,主要优化细节
  4. 3.21日 爬虫小计
  5. 20171207L09-04老男孩Linux运维实战培训-Lamp系列-Apache服务生产实战应用
  6. [js高手之路]this知多少
  7. 附加作业:源自刘乾老师的问题
  8. poj3206(bfs+最小生成树)
  9. python getopt
  10. Windows Server 2008 IIS7.0 发布html和Asp.net网站