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的程序我找到的资料看着都不 ...
随机推荐
- oracle-number(5,2)
insert into emp values(70000.123); 只能存储 整数的前3位, 小数点后面的2位
- 如果Java 失宠于Oracle,那么未来会怎么样?
[编者按]对于前不久 Oracle 裁掉了一部分 Java 布道师,近日一位 Oracle 前高管称其为该机构对Java的「计划报废」.如果这个计划是属实的,那么对于寻常的开发者.已经采用了 Java ...
- eclipse代码自动提示功能设置
一 般默认情况下,Eclipse ,MyEclipse的代码提示功能是比Microsoft Visual Studio的差很多的,主要是Eclipse ,MyEclipse本身有很多选项是默认关闭的, ...
- linux 修改命令行编码 乱码解决方案
修改/etc/default/locale命令:sudo vim /etc/default/locale1将下面这两行 LANG=zh_CN.UTF-8 LANGUAGE=zh_CN:zh 修改为: ...
- codeforces #309 div1 B
题目啰里啰嗦说了一大堆(耐心读完题目就可以秒题了) 首先我们考虑当前置换的开头的循环节的开头 1.如果是1 1->1形成循环节 问题变成i-1的子问题 2.如果是2 1->2->1形 ...
- CURL与PHP-CLI的应用【CLI篇】
CLI的普通应用 什么是PHP-CLI php-cli是php Command Line Interface的简称,即PHP命令行接口,在windows和linux下都是支持PHP-CLI模式的; 为 ...
- python脚本工具-1 制作爬虫下载网页图片
参考:http://www.cnblogs.com/fnng/p/3576154.html 本文参考虫师的博客“python实现简单爬虫功能”,整理分析后抓取其他站点的图片并下载保存在本地. 抓取图片 ...
- Layout Resource官方教程(4)<include>与<merge>
Re-using Layouts with <include/> THIS LESSON TEACHES YOU TO Create a Re-usable Layout Use the ...
- C#.Net 如何动态加载与卸载程序集(.dll或者.exe)4-----Net下的AppDomain编程 [摘录]
最近在对AppDomain编程时遇到了一个问题,卸载AppDomain后,在内存中还保留它加载的DLL的数据,所以即使卸载掉AppDomain,还是无法更新它加载的DLL.看来只有关闭整个进程来更新D ...
- 【HDOJ】2385 Stock
水题,逆向做+优先级队列. /* 2385 */ #include <iostream> #include <sstream> #include <string> ...