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. MySQL两大存储引擎:MyISAM和InnoDB

    Mysql有两大常用的存储引擎MyISAM,InnoDB,默认的形式是前者. 两者基本的差别是对事务处理.外键和行级锁的主持上,InnoDB支持事务处理.外键等高级特性,而MyISAM不支持.MyIS ...

  2. EA类图与代码同步

    画了一段时间的图,愈发感觉到EA是一个强大的软件,而不不过一个绘图工具那么简单. . 随着学习时间的延长.如今写程序并不能像曾经一样随心所欲,想到什么就敲什么了,而是要先绘图(也就是理需求和思路的过程 ...

  3. vsftpd文件服务器安装与配置

    -d<登入目录>:指定用户登入时的启始目录:. -s<shell>:指定用户登入后所使用的shell: /sbin/nologin指的是不允许login当前Linux系统.当用 ...

  4. 006-spring cache-缓存实现-01-原生实现

    一.原生实现 1.1.pom <!-- 缓存 --> <dependency> <groupId>org.springframework.boot</grou ...

  5. Openstack(十)部署nova服务(计算节点)

    在计算节点安装 10.1安装nova计算服务 # 阿里云源详见2.3配置 # yum install openstack-nova-compute 10.2配置nova计算服务 10.2.1配置nov ...

  6. git相关使用技巧和问题

    本地有修改和提交,如何强制用远程的库更新更新.我尝试过用git pull -f,总是提示 You have not concluded your merge. (MERGE_HEAD exists). ...

  7. 利用 TestNG 并行执行用例

    原文地址https://testerhome.com/topics/1639 一.测试类*注1 package com.testerhome; import io.appium.java_client ...

  8. C语言中exit函数的使用

      exit() 结束当前进程/当前程序/,在整个程序中,只要调用 exit ,就结束 return() 是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如果不是,那就是退回上一 ...

  9. Openresty学习汇总

    在锤子科技发布会上,提到给Openresty的捐赠的事情,出于好奇我在是网上查询了Openresty,看到了Openresty的官网(http://openresty.org/en/).看到介绍说的很 ...

  10. 前端学习笔记之css清除浮动float的七种常用方法总结和兼容性处理

    在清除浮动前我们要了解两个重要的定义: 浮动的定义:使元素脱离文档流,按照指定方向发生移动,遇到父级边界或者相邻的浮动元素停了下来. 高度塌陷:浮动元素父元素高度自适应(父元素不写高度时,子元素写了浮 ...