zoukankan      html  css  js  c++  java
  • 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
    ",cnt);
    187         if(cnt){
    188             printf("%d",ans[0]);
    189             for(i=1;i<cnt;i++)
    190                 printf(" %d",ans[i]);
    191         }
    192         putchar('
    ');
    193     }
    194     return 0;
    195 }
  • 相关阅读:
    Leetcode 1489找到最小生成树李关键边和伪关键边
    Leetcode 113 路径总和 II
    hdu 1223 还是畅通工程
    hdu 1087 Super Jumping! Jumping! Jumping!
    hdu 1008 Elevator
    hdu 1037 Keep on Truckin'
    湖工oj 1241 畅通工程
    湖工oj 1162 大武汉局域网
    hdu 2057 A + B Again
    poj 2236 Wireless Network
  • 原文地址:https://www.cnblogs.com/zhsl/p/3272623.html
Copyright © 2011-2022 走看看