HDU 4687 Boke and Tsukkomi (一般图匹配带花树)

Boke and Tsukkomi

Time Limit: 3000/3000 MS (Java/Others)    Memory Limit: 102400/102400 K (Java/Others)
Total Submission(s): 336    Accepted Submission(s): 116

Problem Description A new season of Touhou M-1 Grand Prix is approaching. Girls in Gensokyo cannot wait for participating it. Before the registration, they have to decide which combination they are going to compete as. Every girl in Gensokyo is both a boke (funny girl) and a tsukkomi (straight girl). Every candidate combination is made up of two girls, a boke and a tsukkomi. A girl may belong to zero or more candidate combinations, but one can only register as a member of one formal combination. The host of Touhou M-1 Grand Prix hopes that as many formal combinations as possible can participate in this year. Under these constraints, some candidate combinations are actually redundant as it\’s impossible to register it as a formal one as long as the number of formal combinations has to be maximized. So they want to figure out these redundant combinations and stop considering about them.

 

 

Input There are multiple test cases. Process to the End of File.

The first line of each test case contains two integers: 1 ≤ N ≤ 40 and 1 ≤ M ≤ 
123, where N is the number of girls in Gensokyo, and M is the number of candidate combinations. The following M lines are M candidate combinations, one by each line. Each combination is represented by two integers, the index of the boke girl 1 ≤ B
i ≤ N and the index of the tsukkomi girl 1 ≤ T
i ≤ N, where B
i != T
i.  

 

Output For each test case, output the number of redundant combinations in the first line. Then output the space-separated indexes of the redundant combinations in ascending order in the second line.  

 

Sample Input 4 4 1 3 2 3 2 4 3 1 6 6 1 2 3 2 3 4 5 2 5 4 5 6  

 

Sample Output 1 2 3 2 4 5  

 

Author Zejun Wu (watashi)  

 

Source
2013 Multi-University Training Contest 9  

 

Recommend zhuyuanchen520                 基本上就是一般图匹配的模板题了。     先一开始算总的匹配对数为cnt0. 然后枚举每一对匹配,把该对的点去掉,看匹配数是不是小于cnt0-1,是就是多余的。  

  1 /* ***********************************************
  2 Author        :kuangbin
  3 Created Time  :2013/8/23 19:28:08
  4 File Name     :F:\2013ACM练习\专题学习\图论\一般图匹配带花树\HDU4687.cpp
  5 ************************************************ */
  6 
  7 #include <stdio.h>
  8 #include <string.h>
  9 #include <iostream>
 10 #include <algorithm>
 11 #include <vector>
 12 #include <queue>
 13 #include <set>
 14 #include <map>
 15 #include <string>
 16 #include <math.h>
 17 #include <stdlib.h>
 18 #include <time.h>
 19 using namespace std;
 20 const int MAXN = 50;
 21 int N; //点的个数,点的编号从1到N
 22 bool Graph[MAXN][MAXN];
 23 int Match[MAXN];
 24 bool InQueue[MAXN],InPath[MAXN],InBlossom[MAXN];
 25 int Head,Tail;
 26 int Queue[MAXN];
 27 int Start,Finish;
 28 int NewBase;
 29 int Father[MAXN],Base[MAXN];
 30 int Count;
 31 void Push(int u)
 32 {
 33     Queue[Tail] = u;
 34     Tail++;
 35     InQueue[u] = true;
 36 }
 37 int Pop()
 38 {
 39     int res = Queue[Head];
 40     Head++;
 41     return res;
 42 }
 43 int FindCommonAncestor(int u,int v)
 44 {
 45     memset(InPath,false,sizeof(InPath));
 46     while(true)
 47     {
 48         u = Base[u];
 49         InPath[u] = true;
 50         if(u == Start) break;
 51         u = Father[Match[u]];
 52     }
 53     while(true)
 54     {
 55         v = Base[v];
 56         if(InPath[v])break;
 57         v = Father[Match[v]];
 58     }
 59     return v;
 60 }
 61 void ResetTrace(int u)
 62 {
 63     int v;
 64     while(Base[u] != NewBase)
 65     {
 66         v = Match[u];
 67         InBlossom[Base[u]] = InBlossom[Base[v]] = true;
 68         u = Father[v];
 69         if(Base[u] != NewBase) Father[u] = v;
 70     }
 71 }
 72 void BloosomContract(int u,int v)
 73 {
 74     NewBase = FindCommonAncestor(u,v);
 75     memset(InBlossom,false,sizeof(InBlossom));
 76     ResetTrace(u);
 77     ResetTrace(v);
 78     if(Base[u] != NewBase) Father[u] = v;
 79     if(Base[v] != NewBase) Father[v] = u;
 80     for(int tu = 1; tu <= N; tu++)
 81         if(InBlossom[Base[tu]])
 82         {
 83             Base[tu] = NewBase;
 84             if(!InQueue[tu]) Push(tu);
 85         }
 86 }
 87 void FindAugmentingPath()
 88 {
 89     memset(InQueue,false,sizeof(InQueue));
 90     memset(Father,0,sizeof(Father));
 91     for(int i = 1;i <= N;i++)
 92         Base[i] = i;
 93     Head = Tail = 1;
 94     Push(Start);
 95     Finish = 0;
 96     while(Head < Tail)
 97     {
 98         int u = Pop();
 99         for(int v = 1; v <= N; v++)
100             if(Graph[u][v] && (Base[u] != Base[v]) && (Match[u] != v))
101             {
102                 if((v == Start) || ((Match[v] > 0) && Father[Match[v]] > 0))
103                     BloosomContract(u,v);
104                 else if(Father[v] == 0)
105                 {
106                     Father[v] = u;
107                     if(Match[v] > 0)
108                         Push(Match[v]);
109                     else
110                     {
111                         Finish = v;
112                         return;
113                     }
114                 }
115             }
116     }
117 }
118 void AugmentPath()
119 {
120     int u,v,w;
121     u = Finish;
122     while(u > 0)
123     {
124         v = Father[u];
125         w = Match[v];
126         Match[v] = u;
127         Match[u] = v;
128         u = w;
129     }
130 }
131 void Edmonds()
132 {
133     memset(Match,0,sizeof(Match));
134     for(int u = 1; u <= N; u++)
135         if(Match[u] == 0)
136         {
137             Start = u;
138             FindAugmentingPath();
139             if(Finish > 0)AugmentPath();
140         }
141 }
142 int getMatch()
143 {
144     Edmonds();
145     Count = 0;
146     for(int u = 1; u <= N;u++)
147         if(Match[u] > 0)
148             Count++;
149     return Count/2;
150 }
151 
152 bool g[MAXN][MAXN];
153 pair<int,int>p[150];
154 int main()
155 {
156     //freopen("in.txt","r",stdin);
157     //freopen("out.txt","w",stdout);
158     int m;
159     while(scanf("%d%d",&N,&m)==2)
160     {
161         memset(g,false,sizeof(g));
162         memset(Graph,false,sizeof(Graph));
163         int u,v;
164         for(int i = 1;i <= m;i++)
165         {
166             scanf("%d%d",&u,&v);
167             p[i] = make_pair(u,v);
168             g[u][v] = true;
169             g[v][u] = true;
170             Graph[u][v] = true;
171             Graph[v][u] = true;
172         }
173         int cnt0 = getMatch();
174         //cout<<cnt0<<endl;
175         vector<int>ans;
176         for(int i = 1;i <= m;i++)
177         {
178             u = p[i].first;
179             v = p[i].second;
180             memcpy(Graph,g,sizeof(g));
181             for(int j = 1;j <= N;j++)
182                 Graph[j][u] = Graph[u][j] = Graph[j][v] = Graph[v][j] = false;
183             int cnt = getMatch();
184             //cout<<cnt<<endl;
185             if(cnt < cnt0-1)
186                 ans.push_back(i);
187         }
188         int sz = ans.size();
189         printf("%d\n",sz);
190         for(int i = 0;i < sz;i++)
191         {
192             printf("%d",ans[i]);
193             if(i < sz-1)printf(" ");
194         }
195         printf("\n");
196     }
197     return 0;
198 }

 

                       

    原文作者:算法小白
    原文地址: https://www.cnblogs.com/kuangbin/p/3278620.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞