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。。。

  1 //STATUS:C++_AC_46MS_236KB
  2 #include <functional>
  3 #include <algorithm>
  4 #include <iostream>
  5 //#include <ext/rope>
  6 #include <fstream>
  7 #include <sstream>
  8 #include <iomanip>
  9 #include <numeric>
 10 #include <cstring>
 11 #include <cassert>
 12 #include <cstdio>
 13 #include <string>
 14 #include <vector>
 15 #include <bitset>
 16 #include <queue>
 17 #include <stack>
 18 #include <cmath>
 19 #include <ctime>
 20 #include <list>
 21 #include <set>
 22 //#include <map>
 23 using namespace std;
 24 //#pragma comment(linker,"/STACK:102400000,102400000")
 25 //using namespace __gnu_cxx;
 26 //define
 27 #define pii pair<int,int>
 28 #define mem(a,b) memset(a,b,sizeof(a))
 29 #define lson l,mid,rt<<1
 30 #define rson mid+1,r,rt<<1|1
 31 #define PI acos(-1.0)
 32 //typedef
 33 typedef __int64 LL;
 34 typedef unsigned __int64 ULL;
 35 //const
 36 const int N=42;
 37 const int INF=0x3f3f3f3f;
 38 const int MOD=100000,STA=8000010;
 39 const LL LNF=1LL<<60;
 40 const double EPS=1e-8;
 41 const double OO=1e15;
 42 const int dx[4]={-1,0,1,0};
 43 const int dy[4]={0,1,0,-1};
 44 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
 45 //Daily Use ...
 46 inline int sign(double x){return (x>EPS)-(x<-EPS);}
 47 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
 48 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
 49 template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
 50 template<class T> inline T Min(T a,T b){return a<b?a:b;}
 51 template<class T> inline T Max(T a,T b){return a>b?a:b;}
 52 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
 53 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
 54 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
 55 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
 56 //End
 57 
 58 int a,b;
 59 int n,m;
 60 int head,tail,Start,Finish;
 61 int link[N];     //表示哪个点匹配了哪个点
 62 int Father[N];   //这个就是增广路的Father……但是用起来太精髓了
 63 int Base[N];     //该点属于哪朵花
 64 int Q[N];
 65 bool mark[N];
 66 bool map[N][N];
 67 bool InBlossom[N];
 68 bool in_Queue[N];
 69 
 70 void BlossomContract(int x,int y)
 71 {
 72     fill(mark,mark+n+1,false);
 73     fill(InBlossom,InBlossom+n+1,false);
 74     #define pre Father[link[i]]
 75     int lca,i;
 76     for (i=x;i;i=pre) {i=Base[i]; mark[i]=true; }
 77     for (i=y;i;i=pre) {i=Base[i]; if (mark[i]) {lca=i; break;} }  //寻找lca之旅……一定要注意i=Base[i]
 78     for (i=x;Base[i]!=lca;i=pre){
 79         if (Base[pre]!=lca) Father[pre]=link[i]; //对于BFS树中的父边是匹配边的点,Father向后跳
 80         InBlossom[Base[i]]=true;
 81         InBlossom[Base[link[i]]]=true;
 82     }
 83     for (i=y;Base[i]!=lca;i=pre){
 84         if (Base[pre]!=lca) Father[pre]=link[i]; //同理
 85         InBlossom[Base[i]]=true;
 86         InBlossom[Base[link[i]]]=true;
 87     }
 88     #undef pre
 89     if (Base[x]!=lca) Father[x]=y;     //注意不能从lca这个奇环的关键点跳回来
 90     if (Base[y]!=lca) Father[y]=x;
 91     for (i=1;i<=n;i++){
 92         if(i==a || i==b)continue;
 93         if (InBlossom[Base[i]]){
 94             Base[i]=lca;
 95             if (!in_Queue[i]){
 96                 Q[++tail]=i;
 97                 in_Queue[i]=true;     //要注意如果本来连向BFS树中父结点的边是非匹配边的点,可能是没有入队的
 98             }
 99         }
100     }
101 }
102 
103 void Change()
104 {
105     int x,y,z;
106     z=Finish;
107     while (z){
108         y=Father[z];
109         x=link[y];
110         link[y]=z;
111         link[z]=y;
112         z=x;
113     }
114 }
115 
116 void FindAugmentPath()
117 {
118     fill(Father,Father+n+1,0);
119     fill(in_Queue,in_Queue+n+1,false);
120     for (int i=1;i<=n;i++) Base[i]=i;  //Init属于同一花朵
121     head=0; tail=1;
122     Q[1]=Start; //当前节点进入队列
123     in_Queue[Start]=1;
124     while (head!=tail){
125         int x=Q[++head];
126         for (int y=1;y<=n;y++){
127             if(y==a || y==b)continue;
128             if (map[x][y] && Base[x]!=Base[y] && link[x]!=y){   //无意义的边
129                 if ( Start==y || link[y] && Father[link[y]] )    //精髓地用Father表示该点是否
130                     BlossomContract(x,y);
131                 else if (!Father[y]){
132                     Father[y]=x;
133                     if (link[y]){
134                         Q[++tail]=link[y];
135                         in_Queue[link[y]]=true;
136                     }
137                     else{
138                         Finish=y;
139                         Change();
140                         return;
141                     }
142                 }
143             }
144         }
145     }
146 }
147 
148 int Edmonds()
149 {
150     int i,cnt=0;
151     memset(link,0,sizeof(link));
152     memset(Father,0,sizeof(Father));
153     for (Start=1;Start<=n;Start++){
154         if(Start==a || Start==b)continue;
155         if (link[Start]==0)
156             FindAugmentPath();   //如果点没有匹配,那么找BFS增广路
157     }
158 
159     for(i=1;i<=n;i++)
160         if(link[i])cnt++;
161     return cnt;
162 }
163 
164 int e[130][2],ans[130];
165 
166 int main(){
167  //   freopen("in.txt","r",stdin);
168     int i,j,hig,cnt;
169     while(~scanf("%d%d",&n,&m))
170     {
171         mem(map,0);
172         for(i=0;i<m;i++){
173             scanf("%d%d",&e[i][0],&e[i][1]);
174             map[e[i][0]][e[i][1]]=map[e[i][1]][e[i][0]]=true;
175         }
176 
177         a=b=-1;
178         hig=Edmonds();
179         cnt=0;
180         for(i=0;i<m;i++){
181             a=e[i][0],b=e[i][1];
182             int t=Edmonds();
183             if(t<hig-2)ans[cnt++]=i+1;
184         }
185 
186         printf("%d\n",cnt);
187         if(cnt){
188             printf("%d",ans[0]);
189             for(i=1;i<cnt;i++)
190                 printf(" %d",ans[i]);
191         }
192         putchar('\n');
193     }
194     return 0;
195 }

 

posted @ 2013-08-21 14:39  zhsl  阅读(606)  评论(0编辑  收藏  举报