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
 

 

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 }

 

 
 
 
 
 
 
 
 
 
 
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值