HDU-4687 Boke and Tsukkomi 带花树,枚举
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4687
题意:给一个无向图,求所有的最大匹配的情况所不包含的边。。
数据比较小,直接枚举边。先求一次最大匹配hig,然后依次枚举所有边,假设此边为一个匹配,那么删掉边的两个节点,然后再剩下的图中求最大匹配t,如果t<hig-1那么就是不包含的边了。关于一般图上的最大匹配算法,O(n^3)的Edmonds's matching algorithm,理解起来比较容易,但是写起来比较麻烦,收集了一个模板,by Amber。。。
//STATUS:C++_AC_46MS_236KB
#include <functional>
#include <algorithm>
#include <iostream>
//#include <ext/rope>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cstring>
#include <cassert>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <list>
#include <set>
//#include <map>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,102400000")
//using namespace __gnu_cxx;
//define
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI acos(-1.0)
//typedef
typedef __int64 LL;
typedef unsigned __int64 ULL;
//const
const int N=;
const int INF=0x3f3f3f3f;
const int MOD=,STA=;
const LL LNF=1LL<<;
const double EPS=1e-;
const double OO=1e15;
const int dx[]={-,,,};
const int dy[]={,,,-};
const int day[]={,,,,,,,,,,,,};
//Daily Use ...
inline int sign(double x){return (x>EPS)-(x<-EPS);}
template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
template<class T> inline T Min(T a,T b){return a<b?a:b;}
template<class T> inline T Max(T a,T b){return a>b?a:b;}
template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
//End int a,b;
int n,m;
int head,tail,Start,Finish;
int link[N]; //表示哪个点匹配了哪个点
int Father[N]; //这个就是增广路的Father……但是用起来太精髓了
int Base[N]; //该点属于哪朵花
int Q[N];
bool mark[N];
bool map[N][N];
bool InBlossom[N];
bool in_Queue[N]; void BlossomContract(int x,int y)
{
fill(mark,mark+n+,false);
fill(InBlossom,InBlossom+n+,false);
#define pre Father[link[i]]
int lca,i;
for (i=x;i;i=pre) {i=Base[i]; mark[i]=true; }
for (i=y;i;i=pre) {i=Base[i]; if (mark[i]) {lca=i; break;} } //寻找lca之旅……一定要注意i=Base[i]
for (i=x;Base[i]!=lca;i=pre){
if (Base[pre]!=lca) Father[pre]=link[i]; //对于BFS树中的父边是匹配边的点,Father向后跳
InBlossom[Base[i]]=true;
InBlossom[Base[link[i]]]=true;
}
for (i=y;Base[i]!=lca;i=pre){
if (Base[pre]!=lca) Father[pre]=link[i]; //同理
InBlossom[Base[i]]=true;
InBlossom[Base[link[i]]]=true;
}
#undef pre
if (Base[x]!=lca) Father[x]=y; //注意不能从lca这个奇环的关键点跳回来
if (Base[y]!=lca) Father[y]=x;
for (i=;i<=n;i++){
if(i==a || i==b)continue;
if (InBlossom[Base[i]]){
Base[i]=lca;
if (!in_Queue[i]){
Q[++tail]=i;
in_Queue[i]=true; //要注意如果本来连向BFS树中父结点的边是非匹配边的点,可能是没有入队的
}
}
}
} void Change()
{
int x,y,z;
z=Finish;
while (z){
y=Father[z];
x=link[y];
link[y]=z;
link[z]=y;
z=x;
}
} void FindAugmentPath()
{
fill(Father,Father+n+,);
fill(in_Queue,in_Queue+n+,false);
for (int i=;i<=n;i++) Base[i]=i; //Init属于同一花朵
head=; tail=;
Q[]=Start; //当前节点进入队列
in_Queue[Start]=;
while (head!=tail){
int x=Q[++head];
for (int y=;y<=n;y++){
if(y==a || y==b)continue;
if (map[x][y] && Base[x]!=Base[y] && link[x]!=y){ //无意义的边
if ( Start==y || link[y] && Father[link[y]] ) //精髓地用Father表示该点是否
BlossomContract(x,y);
else if (!Father[y]){
Father[y]=x;
if (link[y]){
Q[++tail]=link[y];
in_Queue[link[y]]=true;
}
else{
Finish=y;
Change();
return;
}
}
}
}
}
} int Edmonds()
{
int i,cnt=;
memset(link,,sizeof(link));
memset(Father,,sizeof(Father));
for (Start=;Start<=n;Start++){
if(Start==a || Start==b)continue;
if (link[Start]==)
FindAugmentPath(); //如果点没有匹配,那么找BFS增广路
} for(i=;i<=n;i++)
if(link[i])cnt++;
return cnt;
} int e[][],ans[]; int main(){
// freopen("in.txt","r",stdin);
int i,j,hig,cnt;
while(~scanf("%d%d",&n,&m))
{
mem(map,);
for(i=;i<m;i++){
scanf("%d%d",&e[i][],&e[i][]);
map[e[i][]][e[i][]]=map[e[i][]][e[i][]]=true;
} a=b=-;
hig=Edmonds();
cnt=;
for(i=;i<m;i++){
a=e[i][],b=e[i][];
int t=Edmonds();
if(t<hig-)ans[cnt++]=i+;
} printf("%d\n",cnt);
if(cnt){
printf("%d",ans[]);
for(i=;i<cnt;i++)
printf(" %d",ans[i]);
}
putchar('\n');
}
return ;
}
HDU-4687 Boke and Tsukkomi 带花树,枚举的更多相关文章
- HDU 4687 Boke and Tsukkomi (一般图匹配带花树)
Boke and Tsukkomi Time Limit: 3000/3000 MS (Java/Others) Memory Limit: 102400/102400 K (Java/Othe ...
- HDU 4687 Boke and Tsukkomi 一般图匹配,带花树,思路,输出注意空行 难度:4
http://acm.hdu.edu.cn/showproblem.php?pid=4687 此题求哪些边在任何一般图极大匹配中都无用,对于任意一条边i,设i的两个端点分别为si,ti, 则任意一个极 ...
- HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】
<题目链接> 题目大意: 给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的. 解题分析: 所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义.那怎样 ...
- hdu 4687 Boke and Tsukkomi
Dancing link twice. Find the maximum combination numbers in the first time. Enumerate each node, dan ...
- HDOJ 4687 Boke and Tsukkomi 一般图最大匹配带花树+暴力
一般图最大匹配带花树+暴力: 先算最大匹配 C1 在枚举每一条边,去掉和这条边两个端点有关的边.....再跑Edmonds得到匹配C2 假设C2+2==C1则这条边再某个最大匹配中 Boke and ...
- kuangbin带你飞 匹配问题 二分匹配 + 二分图多重匹配 + 二分图最大权匹配 + 一般图匹配带花树
二分匹配:二分图的一些性质 二分图又称作二部图,是图论中的一种特殊模型. 设G=(V,E)是一个无向图,如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j ...
- Hdu4687 Boke and Tsukkomi
Boke and Tsukkomi Time ...
- 【Learning】带花树——一般图最大匹配
一般图最大匹配--带花树 问题 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. 这个问题的退化版本就是二分图最大匹配. 由于二分图中不存在奇环,偶环对最大匹配并无 ...
- [转]带花树,Edmonds's matching algorithm,一般图最大匹配
看了两篇博客,觉得写得不错,便收藏之.. 首先是第一篇,转自某Final牛 带花树……其实这个算法很容易理解,但是实现起来非常奇葩(至少对我而言). 除了wiki和amber的程序我找到的资料看着都不 ...
随机推荐
- Linux bash shell脚本语法入门
1.基础 #!/bin/bash //bash脚本第一句都是这个,他会让系统指定以bash来解释这个脚本 # //shell脚本注释符号 2.变量和使用 HOME= ...
- HDU4502吉哥系列故事——临时工计划
http://acm.hdu.edu.cn/showproblem.php?pid=4502 题意 :这个是中文题,我就不再详述了. 思路 : 以前做过一个活动区间选择,结果就按着那个思路敲了,后来发 ...
- HDU1429+bfs+状态压缩
bfs+状态压缩思路:用2进制表示每个钥匙是否已经被找到.. /* bfs+状态压缩 思路:用2进制表示每个钥匙是否已经被找到. */ #include<algorithm> #inclu ...
- Java中List的排序
第一种方法,就是list中对象实现Comparable接口,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 2 ...
- SPRING IN ACTION 第4版笔记-第九章Securing web applications-007-设置LDAP server比较密码(contextSource、root()、ldif()、)
一.LDAP server在哪 By default, Spring Security’s LDAP authentication assumes that the LDAP server is li ...
- 网上图书商城项目学习笔记-036工具类之CommonUtils及日期转换器
1.CommonUtils.java package cn.itcast.commons; import java.util.Map; import java.util.UUID; import or ...
- bugumongo--ConnectToMongoDB
连接MongoDB 在能够对MongDB进行操作之前,需要使用BuguConnection连接到MongoDB数据库.代码如下: BuguConnection conn = BuguConnectio ...
- 转载:C++ map的基本操作和使用
声明:本文转自:http://www.cnblogs.com/hailexuexi/archive/2012/04/10/2440209.html 1.map简介 map是一类关联式容器.它的特点是增 ...
- IE9 表格错位bug
最近做项目的时候,出现一个只在原生IE9(非模拟)下的bug. bug图片如下: 以上两个模块的html代码和样式都是一样的,然而下面的显示却出现了各种对齐的bug. 用IE9的调试器查看,代码完全一 ...
- awesome-java
Awesome Java A curated list of awesome Java frameworks, libraries and software. Awesome Java Ancient ...