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 }