http://acm.hdu.edu.cn/showproblem.php?pid=4687

此题求哪些边在任何一般图极大匹配中都无用,对于任意一条边i,设i的两个端点分别为si,ti,

则任意一个极大匹配中都必然有si或ti至少一个点被匹配,当在图中去掉si,ti两个点时,匹配数会损失一个或两个.

如果损失两个,就说明在极大匹配中这两个点分别连接不同的边,于是边i是无用的

所以总体思路:一般图匹配求出最大匹配数cnt0,分别试着去掉每条边的端点,再次匹配,匹配数如果小于cnt0-1,则这条边无用,记录

ATTENTION:如果无用边数为0,仍然需要输出一个空行

带花树思想简介:

对于一对匹配点,设其中一个是S类型点,另外与之配对的是T点,如图

那么对于需要被增广的某个S类型点u,以及与它相连的点v有

1. v是T类型点
2. v还没有被匹配过

3. v是S类型点

三种情况

设match[i]是i的匹配点

对于第1)种情况,即使接上u,v,断开v和match[v],重整整个增广路也不会影响结果,忽略

对于第2)种情况,就像二分图一样,直接接上u,v并增广路取反

对于第3)种情况,有a. v不在当前增广路上 b.v在当前增广路上

对于3.a)情况,把v加入当前增广路,把两条增广路合并,或者说是把v的开花树并入u的

对于3.b)情况,设r为v,u的最近公共祖先,那么r-v-u-r形成了奇环,把奇环缩为一点,这个点就是开花算法的花,设新图为G',原图为G,可以证明G中有对应G的增广路,因为奇数环上任意一点都可以断开形成新增广路,所以都可以作为s点,不过一次只能断开一处

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <assert.h>
using namespace std; const int MAXN = 45;
int n;//人数,start from 1
bool del[MAXN];//是否不可用
int e[MAXN][MAXN],sz[MAXN];//图
int match[MAXN];//对应边
bool inQue[MAXN],inPath[MAXN],inBlossom[MAXN];//状态
int que[MAXN],head,tail;//s点加入此队列更新
int start,finish;//增广路取反的开始点,结束点
int newFather;//开花算法
int nxt[MAXN],father[MAXN];//nxt 用于遍历开花树 father 标示所属花 void push(int u){
que[tail] = u;
tail++;
inQue[u] = true;
}
int pop(){
int res = que[head];
head++;
return res;
}
int findCommonAncestor(int u,int v){
memset(inPath,false,sizeof(inPath));
while(true){
u = father[u];
inPath[u] = true;
if(u == start) break;
u = nxt[match[u]];
}
while(true){
v = father[v];
if(inPath[v])break;
v = nxt[match[v]];
}
return v;
}
void resetTrace(int u){//连环
int v;
while(father[u] != newFather){
v = match[u];
inBlossom[father[u]] = inBlossom[father[v]] = true;
u = nxt[v];
if(father[u] != newFather) nxt[u] = v;
}
}
void bloosomContract(int u,int v){//连环
newFather = findCommonAncestor(u,v);
memset(inBlossom,false,sizeof(inBlossom));
resetTrace(u);
resetTrace(v);
if(father[u] != newFather) nxt[u] = v;
if(father[v] != newFather) nxt[v] = u;
for(int tu = 1; tu <= n; tu++)
if(inBlossom[father[tu]]){
father[tu] = newFather;
if(!inQue[tu]) push(tu);
}
}
void findAugmentingPath(){//增广主过程
memset(inQue,false,sizeof(inQue));
memset(nxt,0,sizeof(nxt));
for(int i = 1;i <= n;i++)father[i] = i;
head = tail = 1;
push(start);
finish = 0;
while(head < tail){
int u = pop();
assert(!del[u]);
for(int p = 0; p < sz[u]; p++){
int v=e[u][p];
if(!del[v] && (father[u] != father[v]) && (match[u] != v)){//v可用,u,v不在同一花中,u,v不是早已连接
if((v == start) || ((match[v] > 0) && nxt[match[v]] > 0))//奇数环,开花
bloosomContract(u,v);
else if(nxt[v] == 0){//合并开花树
nxt[v] = u;
if(match[v] > 0)
push(match[v]);
else{
finish = v;//找到配对点,成功
return;
}
}
}
}
}
}
void aug(){//增广路取反
int u,v,w;
u = finish;
while(u > 0){
v = nxt[u];
w = match[v];
match[v] = u;
match[u] = v;
u = w;
}
}
void Edmonds(){//增广算法
memset(match,0,sizeof(match));
for(int i = 1; i <= n; i++)
if(!del[i]&&match[i] == 0){
start = i;
findAugmentingPath();
if(finish > 0)aug();
}
}
int getMatch(){//统计结果
Edmonds();
int cnt = 0;
for(int i = 1; i <= n;i++)
if(match[i] > 0)
cnt++;
return cnt/2;
} bool g[MAXN][MAXN];
int from[MAXN*4],to[MAXN*4];
int heap[MAXN*4];
int main(){
int m;
while(scanf("%d%d",&n,&m)==2){
memset(g,false,sizeof(g));
memset(del,false,sizeof(del));
memset(sz,0,sizeof(sz));
for(int i = 0;i <m;i++){
scanf("%d%d",from+i,to+i);
int f=from[i],t=to[i];
if(!g[f][t]){
g[f][t]=g[t][f]=true;
e[f][sz[f]++]=t;
e[t][sz[t]++]=f;
}
}
int cnt0 = getMatch(); int ans=0;
for(int i = 0;i <m;i++){
int f=from[i],t=to[i];
del[f]=del[t]=true;
int cnt = getMatch();
if(cnt == cnt0-2){heap[ans++]=i+1;}
del[t]=del[f]=false;
}
printf("%d\n",ans);
for(int i=0;i<ans;i++){
printf("%d%c",heap[i],i==ans-1?'\n':' ');
}
if(ans==0)puts("");
}
return 0;
}

  

HDU 4687 Boke and Tsukkomi 一般图匹配,带花树,思路,输出注意空行 难度:4的更多相关文章

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

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

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

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

  3. HDU 4687 Boke and Tsukkomi (一般图匹配带花树)

    Boke and Tsukkomi Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Othe ...

  4. kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树

    二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j ...

  5. URAL 1099. Work Scheduling (一般图匹配带花树)

    1099. Work Scheduling Time limit: 0.5 secondMemory limit: 64 MB There is certain amount of night gua ...

  6. URAL1099 Work Scheduling —— 一般图匹配带花树

    题目链接:https://vjudge.net/problem/URAL-1099 1099. Work Scheduling Time limit: 0.5 secondMemory limit: ...

  7. URAL1099. Work Scheduling(一般图匹配带花树开花算法)

    1099. Work Scheduling Time limit: 0.5 second Memory limit: 64 MB There is certain amount of night gu ...

  8. hdu 4687 Boke and Tsukkomi

    Dancing link twice. Find the maximum combination numbers in the first time. Enumerate each node, dan ...

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

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

随机推荐

  1. Linux常用命令【总结】

    Linux命令中文版详解:https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/index.html Linux系统,我用过的有centos和 ...

  2. ssh 配置文件讲解大全 ssh调试模式 sftp scp strace进行调试 特权分离

    ssh 配置文件讲解大全  ssh调试模式  sftp scp strace进行调试  特权分离 http://blog.chinaunix.net/uid-16728139-id-3265394.h ...

  3. weiwo.wxmmd.com将您重定向的次数过多。尝试清除 Cookie.

    折腾了很久,最后更换PHP版本解决了,我的项目用的tp3.1.2,出现上图问题时的php版本是7.1,换回5.6就没有这个问题.希望能为大家提供一个思路.

  4. linux进程间通讯的几种方式的特点和优缺点

    # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系.# 有名管道 (named pipe) : 有名管道也是 ...

  5. [转]AJAX 跨源 HTTP 请求

    转自OSChina, 原文: http://www.oschina.net/translate/ajax-cross-origin-http-request 背景 跨源HTTP请求(也称跨域AJAX请 ...

  6. 1.2、Django 视图与网址__进阶

    Django 视图与网址进阶 1.1.简单使用: 把我们新定义的app加到settings.py中的INSTALL_APPS中 修改 HelloDjango/HelloDjango/settings. ...

  7. SQL: 拼接列

    1. 因工作需要,需把两列(id,created_by)拼接成一列,结果很有意思,前5个值都是null. 2.解决方法:null加减乘除任何值都等于null,所以使用isnull函数先处理下列的值再拼 ...

  8. C#——JSON操作类简单封装(DataContractJsonSerializer)

    Framework版本:.Net Framework 4 使用DataContractJsonSerializer时,实体请使用注解,格式如下 1.实体使用注解,并且提供get和set的public访 ...

  9. Underscore-逐行分析

    标签: // Underscore.js 1.8.3// http://underscorejs.org// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud ...

  10. python使用cx_Oracle连接oracle

    1.使用pip命令安装cx_Oracle $ pip install cx_Oracle 2.安装oracle客户端,并添加到path 下载路径: http://www.oracle.com/tech ...