HDU 4687 Boke and Tsukkomi 一般图匹配,带花树,思路,输出注意空行 难度:4
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的更多相关文章
- HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力
一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...
- HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】
<题目链接> 题目大意: 给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的. 解题分析: 所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义.那怎样 ...
- HDU 4687 Boke and Tsukkomi (一般图匹配带花树)
Boke and Tsukkomi Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Othe ...
- kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树
二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j ...
- URAL 1099. Work Scheduling (一般图匹配带花树)
1099. Work Scheduling Time limit: 0.5 secondMemory limit: 64 MB There is certain amount of night gua ...
- URAL1099 Work Scheduling —— 一般图匹配带花树
题目链接:https://vjudge.net/problem/URAL-1099 1099. Work Scheduling Time limit: 0.5 secondMemory limit: ...
- URAL1099. Work Scheduling(一般图匹配带花树开花算法)
1099. Work Scheduling Time limit: 0.5 second Memory limit: 64 MB There is certain amount of night gu ...
- hdu 4687 Boke and Tsukkomi
Dancing link twice. Find the maximum combination numbers in the first time. Enumerate each node, dan ...
- ZOJ 3316 Game 一般图最大匹配带花树
一般图最大匹配带花树: 建图后,计算最大匹配数. 假设有一个联通块不是完美匹配,先手就能够走那个没被匹配到的点.后手不论怎么走,都必定走到一个被匹配的点上.先手就能够顺着这个交错路走下去,最后一定是后 ...
随机推荐
- 商铺项目(使用DES加密配置信息)
package com.ouyan.o2o.util; import java.security.Key; import java.security.SecureRandom; import java ...
- mysql索引详解(转)
什么是索引 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的 ...
- Openstack(十)部署nova服务(计算节点)
在计算节点安装 10.1安装nova计算服务 # 阿里云源详见2.3配置 # yum install openstack-nova-compute 10.2配置nova计算服务 10.2.1配置nov ...
- Spark SQL的整体实现逻辑
1.sql语句的模块解析 当我们写一个查询语句时,一般包含三个部分,select部分,from数据源部分,where限制条件部分,这三部分的内容在sql中有专门的名称: 当我们写sql时,如上图所示, ...
- Selenium IDE的一些操作
1.运行速度过快时,可能出现找不到元素的情况,影响运行结果,将速度调慢慢一些,就可以运行成功. 如果为其他情况找不到元素,则需要另外找原因,有可能元素定位有问题,有可能无该元素. 2.导出录制的脚本为 ...
- 系统管理命令之who
作为一名系统管理员,我们需要弄清楚在一个特定的时间点都有谁活跃在系统上.必须严密监视我们的服务器.但是,我们当然不可能一天24小时都盯着系统.在linux系统中,我们可以使用who命令查看登录者信息. ...
- ACM ICPC, JUST Collegiate Programming Contest (2018) Solution
A:Zero Array 题意:两种操作, 1 p v 将第p个位置的值改成v 2 查询最少的操作数使得所有数都变为0 操作为可以从原序列中选一个非0的数使得所有非0的数减去它,并且所有数不能 ...
- Flask添加翻页功能(非sqlalchemy)
最近做flask的项目,需要增加翻页的功能,网上找的教程都是结合sqlalchemy的,可是我用的不是sqlalchemy,肿木办呢? 以下是我的做法 一.前端 1.传递页码 前端我使用ajax提交表 ...
- mongoose 获取某个存在的collecion 里的数据
在创建Schma 时指定对应的collection var db_url = 'mongodb://localhost:27017/test'; var db = mongoose.connect(d ...
- 前端面试题之 sum(2)(3) (链式调用,toString,柯里化,数组操作)
写一个函数让下面两个输出结果相同:console.log(sum(2)(3));console.log(sum(2,3)); var sum = (function() { var list = [] ...