题目链接: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 带花树,枚举的更多相关文章

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

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

  2. HDU 4687 Boke and Tsukkomi 一般图匹配,带花树,思路,输出注意空行 难度:4

    http://acm.hdu.edu.cn/showproblem.php?pid=4687 此题求哪些边在任何一般图极大匹配中都无用,对于任意一条边i,设i的两个端点分别为si,ti, 则任意一个极 ...

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

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

  4. hdu 4687 Boke and Tsukkomi

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

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

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

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

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

  7. Hdu4687 Boke and Tsukkomi

    Boke and Tsukkomi                                                                               Time ...

  8. 【Learning】带花树——一般图最大匹配

    一般图最大匹配--带花树 问题 ​ 给定一个图,求该图的最大匹配.即找到最多的边,使得每个点至多属于一条边. ​ 这个问题的退化版本就是二分图最大匹配. ​ 由于二分图中不存在奇环,偶环对最大匹配并无 ...

  9. [转]带花树,Edmonds's matching algorithm,一般图最大匹配

    看了两篇博客,觉得写得不错,便收藏之.. 首先是第一篇,转自某Final牛 带花树……其实这个算法很容易理解,但是实现起来非常奇葩(至少对我而言). 除了wiki和amber的程序我找到的资料看着都不 ...

随机推荐

  1. C++ 嵌套类使用(一)

    一.嵌套类 在一个类的内部定义另一个类,我们称之为嵌套类(nested class),或者嵌套类型.之所以引入这样一个嵌套类,往往是因为外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的 ...

  2. 【leetcode】Permutations II (middle)

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  3. struts2+jquery+ajax实现上传&&校验实例

    一直以为ajax不能做上传,直到最近看了一些文章.需要引入AjaxFileUploaderV2.1.zip,下载链接:http://pan.baidu.com/s/1i3L7I2T 代码和相关配置如下 ...

  4. android应用崩溃的调试方法(c++ lib so文件库崩溃)

    android调试工具addr2line使用: 1.将ndk中的arm-linux-androideabi-addr2line可执行文件的路径加入配置文件~/.bashrc中,例如: export P ...

  5. 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 ...

  6. Linux 阿里云挂载新分区

    阿里云服务器可以自己购买数据盘并挂载使用,虽然官方也提供了挂载的教程,但是还是有些朋友不清楚其中的细节,为此,我在这里来给大家分享一下详细的挂载办法. 工具/原料 已经购买开通阿里云服务器,并且在开通 ...

  7. POJ2524——Ubiquitous Religions

    Ubiquitous Religions Description There are so many different religions in the world today that it is ...

  8. php实现自动运行文件

    autoexec.php <?php ignore_user_abort(); //即使Client断开(如关掉浏览器),PHP脚本也可以继续执行. set_time_limit(30); // ...

  9. mac terminal终端ls命令参数详解

    原文:https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/ls.1.html -a ...

  10. poj1195Mobile phones(二维树状数组)

    http://poj.org/problem?id=1195 模版题 i写成k了 找了一个多小时没找出来.. #include <iostream> #include<cstring ...