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 }
  • 相关阅读:
    最长公共子序列(LCS)
    数组分割问题
    Trie树
    BitMap(比特位)
    KMP算法——字符串匹配
    排序算法
    概率问题
    【设计模式】——访问者模式
    【设计模式】——解释器模式
    【设计模式】——享元模式
  • 原文地址:https://www.cnblogs.com/zhsl/p/3272623.html
Copyright © 2011-2022 走看看