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. CF1028E Restore Array 构造

    正解:构造 解题报告: 传送门! 是的灵巧还在写构造,,,不知道484我做题太慢的缘故我感觉我做了好久的构造了然而一半的题目都没做完QAQ 要哭出来了QAQ 然后说下这题的解法,开始花了这——么的时间 ...

  2. proc_create函数内幕初探

    一直以为PROC文件系统很是晦涩难懂,平时仅仅是使用它,不愿意去触碰内核中的具体实现.今天突发奇想,想看看里面究竟是怎么实现的,结果……真是大跌眼镜,没想到里面并不复杂 关于PROC文件系统的功能以及 ...

  3. 14.Git忽略特殊文件.gitignore

    有些时候,你必须把某些文件放到Git工作目录中,但又不能提交它们,比如保存了数据库密码的配置文件啦,等等,每次git status都会显示Untracked files ...,有强迫症的童鞋心里肯定 ...

  4. day08:软件系统的体系结构&Tomcat详解&Web应用&http协议

        day08 软件系统体系结构     常见软件系统体系结构B/S.C/S 1.1 C/S C/S结构即客户端/服务器(Client/Server),例如QQ: 需要编写服务器端程序,以及客户端 ...

  5. centos linux系统日常管理复习 CPU物理数逻辑核数,iftop ,iotop ,sar ,ps,netstat ,一网卡多IP,mii-tool 连接,ethtool速率,一个网卡配置多个IP,mii-tool 连接,ethtool速率 ,crontab备份, 第十八节课

    centos linux系统日常管理复习 物理CPU和每颗CPU的逻辑核数,uptime ,w,vmstat,iftop ,iotop ,sar ,ps,netstat ,一个网卡配置多个IP,mii ...

  6. Windows 10 升级软件 Windows 10 易升

    进入 https://www.microsoft.com/zh-cn/software-download/windows10 点立即更新,弹出如下下载地址. https://download.micr ...

  7. 谈谈ConcurrentHashMap1.7和1.8的不同实现

    知止而后有定,定而后能静,静而后能安,安而后能虑,虑而后能得. ConcurrentHashMap 在多线程环境下,使用HashMap进行put操作时存在丢失数据的情况,为了避免这种bug的隐患,强烈 ...

  8. java序列化与反序列化(转)

    Java序列化与反序列化是什么?为什么需要序列化与反序列化?如何实现Java序列化与反序列化?本文围绕这些问题进行了探讨. 1.Java序列化与反序列化 Java序列化是指把Java对象转换为字节序列 ...

  9. POJ1175:Starry Night(bfs)

    http://poj.org/problem?id=1175 题目解析: 这个题因为数据的原因可以很水的过,但我因为把1e-8写成了1e-9WA了N遍,一直WA,题目意思很简单就是相似图形(就是求旋转 ...

  10. Sparsity稀疏编码(二)

           为了更进一步的清晰理解大脑皮层对信号编码的工作机制(策略),需要把他们转成数学语言,因为数学语言作为一种严谨的语言,可以利用它推导出期望和要寻找的程式.本节就使用概率推理(bayes v ...