算法原理详见 http://www.csie.ntnu.edu.tw/~u91029/Matching.html

orz 带花树很神奇,挖坑最大权匹配

#include <iostream>
#include <cstring>
#include <cstdio>
#include <deque>
using namespace std;
const int maxn = ;
deque<int> p[maxn]; //树根到x的交错路径
bool adj[maxn][maxn];
int m[maxn]; //记录匹配情况
int d[maxn]; //记录奇点和偶点
int q[maxn], *qf, *qb; //记录可延伸的偶点
int n; void label_one_side(int x, int y, int bi){
for(int i = bi+; i < p[x].size(); i++){
int z = p[x][i];
if(d[z] == ){
p[z] = p[y];
p[z].insert(p[z].end(), p[x].rbegin(), p[x].rend()-i);
d[z] = ;
*qb++ = z;
}
}
} bool BFS(int r){
for(int i = ; i < n; i++) p[i].clear();
p[r].push_back(r);
for(int i = ; i < n; i++) d[i] = -;
d[r] = ;
qf = qb = q;
*qb++ = r;
while(qf < qb){
for(int x = *qf++, y = ; y < n; y++){
if(adj[x][y] && m[y] != y){
if(d[y] == -){
if(m[y] == -){
for(int i = ; i+ < p[x].size(); i += ){
m[p[x][i]] = p[x][i+];
m[p[x][i+]] = p[x][i];
}
m[x] = y; m[y] = x;
return true;
} else {
int z = m[y];
p[z] = p[x];
p[z].push_back(y);
p[z].push_back(z);
d[y] = ; d[z] = ;
*qb++ = z;
}
} else if(d[y] == ) {
int bi = ;
while(bi < p[x].size() && bi < p[y].size() && p[x][bi] == p[y][bi]) bi++;
bi--;
label_one_side(x, y, bi);
label_one_side(y, x, bi);
}
}
}
}
return false;
} int match(){
for(int i = ; i < n; i++) m[i] = -;
int c = ;
for(int i = ; i < n; i++){
if(m[i] == -)
if(BFS(i)) c++;
else m[i] = i;
}
return c;
} int main(){
cin>>n;
int x, y;
while(cin>>x>>y) adj[x][y] = adj[y][x] = true;
match();
}

这个是缩点版本的

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int N = ;
int n;
bool adj[N][N];
int p[N];
int m[N];
int d[N];
int c1[N], c2[N];
int q[N], *qf, *qb; int pp[N];
int f(int x) { return x == pp[x] ? x : pp[x] = f(pp[x]); }
void u(int x, int y) { pp[x] = y; }
int v[N]; void path(int r, int x){
if(r == x) return;
if(d[x] == ){
path(r, p[p[x]]);
int i = p[x], j = p[p[x]];
m[i] = j; m[j] = i;
} else if(d[x] == ){
path(m[x], c1[x]);
path(r, c2[x]);
int i = c1[x], j = c2[x];
m[i] = j; m[j] = i;
}
} int lca(int x, int y, int r){
int i = f(x), j = f(y);
while(i != j && v[i] != && v[j] != ){
v[i] = ; v[j] = ;
if(i != r) i = f(p[i]);
if(j != r) j = f(p[j]);
}
int b = i, z = j; if(v[j] == ) swap(b, z);
for(int i = b; i != z; i = f(p[i])) v[i] = -;
v[z] = -;
return b;
} void contract_one_side(int x, int y, int b){
for(int i = f(x); i != b; i = f(p[i])){
u(i, b);
if(d[i] == ) c1[i] = x, c2[i] = y, *qb++ = i;
}
} bool BFS(int r){
for(int i = ; i < n; i++) pp[i] = i;
for(int i = ; i < n; i++) v[i] = d[i] = -;
d[r] = ;
qf = qb = q;
*qb++ = r;
while(qf < qb){
for(int x = *qf++, y = ; y < n; y++){
if(!adj[x][y] || m[y] == y || f(x) == f(y)) continue;
if(d[y] == -){
if(m[y] == -){
path(r, x);
m[x] = y; m[y] = x;
return true;
} else {
p[y] = x; p[m[y]] = y;
d[y] = ; d[m[y]] = ;
*qb++ = m[y];
}
} else if(d[f(y)] == ){
int b = lca(x, y, r);
contract_one_side(x, y, b);
contract_one_side(y, x, b);
}
}
}
return false;
} int main(){ }

Augmenting Path Algorithm : 一般图最大匹配的更多相关文章

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

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

  2. Maximum Cardinality Bipartite Matching: Augmenting Path Algorithm

    http://www.csie.ntnu.edu.tw/~u91029/Matching.html int nx,ny; int mx[N],my[N]; bool vy[N]; bool g[N][ ...

  3. [转载]Maximum Flow: Augmenting Path Algorithms Comparison

    https://www.topcoder.com/community/data-science/data-science-tutorials/maximum-flow-augmenting-path- ...

  4. UOJ79 一般图最大匹配

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. CentOS7 minimal 没有netstat命令

    在CentOS 7 minimal中使用netstat 时,发现显示如下,明显没有了netstat 命令 [root@localhost ~]# netstat -a -bash: netstat: ...

  2. SQL中EXCEPT函数在 Mysql 和 sqlServer 中的替代方法

    示例摘自:极客代码:http://wiki.jikexueyuan.com/project/sql/useful-functions/except-clause.html EXCEPT 子句 EXCE ...

  3. (转载)jsp的内部方法jspInit(),_jspService(),jspDestroy()

    jspInit(){}:jsp Page被初始化的时候调用该方法,并且该方法仅在初始化时执行一次,所以可以在这里进行一些初始化的参数配置等一次性工作,由作者创建jspDestroy(){}:jsp P ...

  4. php-5.6.26源代码 - hash存储结构 - 添加

    添加 , (void *)module, sizeof(zend_module_entry), (void**)&module_ptr){ // zend_hash_add 定义在文件“php ...

  5. Hadoop(21)-数据清洗(ELT)简单版

    有一个诸如这样的log日志 去除长度不合法,并且状态码不正确的记录 LogBean package com.nty.elt; /** * author nty * date time 2018-12- ...

  6. 8.2 USB键盘驱动编写和测试

    目标:根据USB驱动分析和上节的USB鼠标驱动,编写键盘驱动,并测试. 一.原理分析 1. 首先通过打印usb_buf[i]中的8字节数据,看一下按键按下之后会接收到什么. 1)通过按完所有键盘按键打 ...

  7. unity开发c#代码

    1.摄像头跟随主角移动,并支持旋转. 开发过程中需要摄像头以一定距离跟随player,同时会进行旋转,属于一种常见的跟随方式. using UnityEngine; using System.Coll ...

  8. python基础之try异常处理、socket套接字基础part1

    异常处理 错误 程序里的错误一般分为两种: 1.语法错误,这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正 2.逻辑错误,人为造成的错误,如数据类型错误.调用方法错误等,这些解 ...

  9. c/c++指针理解

    指针的概念 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址.要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占 ...

  10. 通过transpose和flip实现图像旋转90/180/270度

    在fbc_cv库中,提供了对图像进行任意角度旋转的函数rotate,其实内部也是调用了仿射变换函数warpAffine.如果图像仅是进行90度倍数的旋转,是没有必要用warpAffine函数的.这里通 ...