HDU4687 Boke and Tsukkomi

题目链接:https://vjudge.net/problem/HDU-4687

知识点:  带花树开花算法

解题思路:

  先求出原来的一般图的最大匹配数\(iCnt\). 然后枚举每一个组合,尝试去掉图中所有以这个组合中任意一点为端点的边,求出此时的最大匹配数\(tCnt\),如果\(tCnt<iCnt-1\),则这个组合对于任意一种最大匹配来说都是多余的。

AC代码:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 typedef pair<int,int> P ;
  4 const int maxn = 40+5, maxm = 150;
  5 int N,M;
  6 bool Graph[maxn][maxn],G[maxn][maxn];
  7 int Match[maxn];
  8 bool InQueue[maxn],InPath[maxn],InBlossom[maxn];
  9 int Head,Tail;
 10 int Queue[maxn];
 11 int Start,Finish;
 12 int NewBase;
 13 int Father[maxn],Base[maxn];
 14 
 15 P inp[maxm];
 16 
 17 void Push(int u){
 18     Queue[Tail]=u;
 19     Tail++;
 20     InQueue[u]=true;
 21 }
 22 int Pop(){
 23     int res=Queue[Head];
 24     Head++;
 25     return res;
 26 }
 27 int FindCommonAncestor(int u,int v){
 28     memset(InPath,false,sizeof(InPath));
 29     while(1){
 30         u=Base[u];
 31         InPath[u]=true;
 32         if(u==Start)    break;
 33         u=Father[Match[u]];
 34     }
 35     while(1){
 36         v=Base[v];
 37         if(InPath[v])   break;
 38         v=Father[Match[v]];
 39     }
 40     return v;
 41 }
 42 void ResetTrace(int u){
 43     int v;
 44     while(Base[u]!=NewBase){
 45         v=Match[u];
 46         InBlossom[Base[u]]=InBlossom[Base[v]]=true;
 47         u=Father[v];
 48         if(Base[u]!=NewBase)    Father[u]=v;
 49     }
 50 }
 51 void BloosomContract(int u,int v){
 52     NewBase = FindCommonAncestor(u,v);
 53     memset(InBlossom,false,sizeof(InBlossom));
 54     ResetTrace(u);  ResetTrace(v);
 55     if(Base[u]!=NewBase)    Father[u]=v;
 56     if(Base[v]!=NewBase)    Father[v]=u;
 57     for(int tu=1;tu<=N;tu++){
 58         if(InBlossom[Base[tu]]){
 59             Base[tu]=NewBase;
 60             if(!InQueue[tu])    Push(tu);
 61         }
 62     }
 63 }
 64 void FindAugmentingPath(){
 65     memset(InQueue,false,sizeof(InQueue));
 66     memset(Father,0,sizeof(Father));
 67     for(int i=1;i<=N;i++)   Base[i]=i;
 68     Head=Tail=1;
 69     Push(Start);
 70     Finish=0;
 71     while(Head<Tail){
 72         int u=Pop();
 73         for(int v=1;v<=N;v++){
 74             if(Graph[u][v]&&(Base[u]!=Base[v])&&(Match[u]!=v)){
 75                 if((v==Start)||(Match[v]>0)&&(Father[Match[v]]>0))
 76                     BloosomContract(u,v);
 77                 else if(Father[v]==0){
 78                     Father[v]=u;
 79                     if(Match[v]>0)  Push(Match[v]);
 80                     else{
 81                         Finish=v;
 82                         return;
 83                     }
 84                 }
 85             }
 86         }
 87     }
 88 }
 89 void AugumentPath(){
 90     int u,v,w;
 91     u=Finish;
 92     while(u>0){
 93         v=Father[u];
 94         w=Match[v];
 95         Match[v]=u;
 96         Match[u]=v;
 97         u=w;
 98     }
 99 }
100 void Edmonds(){
101     memset(Match,0,sizeof(Match));
102     for(int u=1;u<=N;u++){
103         if(Match[u]==0){
104             Start =u;
105             FindAugmentingPath();
106             if(Finish>0)    AugumentPath();
107         }
108     }
109 }
110 
111 int main(){
112     int u,v;
113     while(scanf("%d%d",&N,&M)==2){
114         memset(G,false,sizeof(G));
115         memset(Graph,false,sizeof(Graph));
116         for(int i=1;i<=M;i++){
117             scanf("%d%d",&u,&v);
118             inp[i]=make_pair(u,v);
119             Graph[u][v]=Graph[v][u]=G[u][v]=G[v][u]=true;
120         }
121         Edmonds();
122         int iCount=0;
123         for(int u=1;u<=N;u++){
124             if(Match[u]>0)  iCount++;
125         }iCount/=2;
126         vector<int> ans;
127         for(int i=1;i<=M;i++){
128             int u=inp[i].first,v=inp[i].second;
129             for(int j=1;j<=N;j++)   Graph[u][j]=Graph[j][u]=Graph[v][j]=Graph[j][v]=false;
130             Edmonds();
131             int tCount=0;
132             for(int u=1;u<=N;u++){
133                 if(Match[u]>0)  tCount++;
134             }tCount/=2;
135             if(tCount<iCount-1) ans.push_back(i);
136             for(int j=1;j<=N;j++){
137                 Graph[u][j]=G[u][j];
138                 Graph[j][u]=G[j][u];
139                 Graph[v][j]=G[v][j];
140                 Graph[j][v]=G[j][v];
141             }
142         }
143         int sz=ans.size();
144         printf("%d\n",sz);
145         for(int i=0;i<sz;i++){
146             if(i!=0)    printf(" ");
147             printf("%d",ans[i]);
148         }
149         printf("\n");
150     }
151     return 0;
152 }

 

  

posted @ 2018-02-04 20:56  Blogggggg  阅读(213)  评论(0编辑  收藏  举报