HDU 3472 HS BDC (混合图的欧拉路径判断)

HS BDC

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 748    Accepted Submission(s): 290

Problem Description IELTS is around the corner! love8909 has registered for the exam, but he still hasn’t got prepared. Now he decides to take actions. But when he takes out the New Oriental IELTS Vocabulary, he finds there are so many words. But love8909 doesn’t get scared, because he has got a special skill. If he can make a list with some meaningful words, he will quickly remember these words and will not forget them. If the last letter of some word Wa is the same as the first letter of some word Wb, then you can connect these two words and make a list of two words. If you can connect a word to a list, you will make a longer list.

While love8909 is making the list, he finds that some words are still meaningful words if you reverse them. For example, if you reverse the word “pat”, you will get another meaningful word “tap”.

After scanning the vocabulary, love8909 has found there are N words, some of them are meaningful if reversed, while others are not. Now he wonders whether he can remember all these words using his special skill.

The N-word list must contain every word once and only once.  

 

Input An integer T (T <= 50) comes on the first line, indicating the number of test cases.

On the first line of each test cases is an integer N (N <= 1000), telling you that there are N words that love8909 wants to remember. Then comes N lines. Each of the following N lines has this format: word type. Word will be a string with only ‘a’~’z’, and type will be 0(not meaningful when reversed) or 1(meaningful when reversed). The length of each word is guaranteed to be less than 20.

 

 

Output The format of the output is like “Case t: s”, t is the number of the test cases, starting from 1, and s is a string.

For each test case, if love8909 can remember all the words, s will be “Well done!”, otherwise it’s “Poor boy!”

 

 

Sample Input 3 6 aloha 0 arachnid 0 dog 0 gopher 0 tar 1 tiger 0 3 thee 1 earn 0 nothing 0 2 pat 1 acm 0  

 

Sample Output Case 1: Well done! Case 2: Well done! Case 3: Poor boy!
Hint In the first case, the word “tar” is still meaningful when reversed, and love8909 can make a list as “aloha-arachnid-dog-gopher-rat-tiger”. In the second case, the word “thee” is still meaningful when reversed, and love8909 can make a list as “thee-earn-nothing”. In the third case, no lists can be created.  

 

Author allenlowesy  

 

Source
2010 ACM-ICPC Multi-University Training Contest(4)——Host by UESTC        

 

几乎就是模板题了。

先要判断连通。

然后转化成网络流判断欧拉回路。

  1 /* ***********************************************
  2 Author        :kuangbin
  3 Created Time  :2014-2-3 15:00:40
  4 File Name     :E:\2014ACM\专题学习\图论\欧拉路\混合图\HDU3472.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 
 21 const int MAXN = 30;
 22 //最大流部分
 23 const int MAXM = 10000;
 24 const int INF = 0x3f3f3f3f;
 25 struct Edge
 26 {
 27     int to,next,cap,flow;
 28 }edge[MAXM];
 29 int tol;
 30 int head[MAXN];
 31 int gap[MAXN], dep[MAXN], pre[MAXN], cur[MAXN];
 32 void init()
 33 {
 34     tol = 0;
 35     memset(head,-1,sizeof(head));
 36 }
 37 void addedge(int u,int v,int w,int rw = 0)
 38 {
 39     edge[tol].to = v;
 40     edge[tol].cap = w;
 41     edge[tol].next = head[u];
 42     edge[tol].flow = 0;
 43     head[u] = tol++;
 44     edge[tol].to = u;
 45     edge[tol].cap = rw;
 46     edge[tol].next = head[v];
 47     edge[tol].flow = 0;
 48     head[v] = tol++;
 49 }
 50 int sap(int start,int end,int N)
 51 {
 52     memset(gap,0,sizeof(gap));
 53     memset(dep,0,sizeof(dep));
 54     memcpy(cur,head,sizeof(head));
 55     int u = start;
 56     pre[u] = -1;
 57     gap[0] = N;
 58     int ans = 0;
 59     while(dep[start] < N)
 60     {
 61         if(u == end)
 62         {
 63             int Min = INF;
 64             for(int i = pre[u];i != -1;i = pre[edge[i^1].to])
 65                 if(Min > edge[i].cap - edge[i].flow)
 66                     Min = edge[i].cap - edge[i].flow;
 67             for(int i = pre[u]; i != -1;i = pre[edge[i^1].to])
 68             {
 69                 edge[i].flow += Min;
 70                 edge[i^1].flow -= Min;
 71             }
 72             u = start;
 73             ans += Min;
 74             continue;
 75         }
 76         bool flag = false;
 77         int v;
 78         for(int i = cur[u]; i != -1;i = edge[i].next)
 79         {
 80             v = edge[i].to;
 81             if(edge[i].cap - edge[i].flow && dep[v] + 1 == dep[u])
 82             {
 83                 flag = true;
 84                 cur[u] = pre[v] = i;
 85                 break;
 86             }
 87         }
 88         if(flag)
 89         {
 90             u = v;
 91             continue;
 92         }
 93         
 94         int Min = N;
 95         for(int i = head[u];  i != -1;i = edge[i].next)
 96             if(edge[i].cap - edge[i].flow && dep[edge[i].to] < Min)
 97             {
 98                 Min = dep[edge[i].to];
 99                 cur[u] = i;
100             }
101         gap[dep[u]] --;
102         if(!gap[dep[u]])return ans;
103         dep[u] = Min+1;
104         gap[dep[u]]++;
105         if(u != start) u = edge[pre[u]^1].to;
106     }
107     return ans;
108 }
109 
110 int in[30],out[30];
111 int F[30];
112 int find(int x)
113 {
114     if(F[x] == -1)return x;
115     else return F[x] = find(F[x]);
116 }
117 void bing(int u,int v)
118 {
119     int t1 = find(u), t2 = find(v);
120     if(t1 != t2)F[t1] = t2;
121 }
122 char str[100];
123 int main()
124 {
125     //freopen("in.txt","r",stdin);
126     //freopen("out.txt","w",stdout);
127     int T,n;
128     scanf("%d",&T);
129     int iCase = 0;
130     while(T--)
131     {
132         iCase++;
133         scanf("%d",&n);
134         memset(F,-1,sizeof(F));
135         memset(in,0,sizeof(in));
136         memset(out,0,sizeof(out));
137         init();
138         int k;
139         int s = -1;
140         while(n--)
141         {
142             scanf("%s%d",str,&k);
143             int len = strlen(str);
144             int u = str[0] - 'a';
145             int v = str[len-1] - 'a';
146             out[u]++;
147             in[v]++;
148             s = u;
149             if(k == 1)
150                 addedge(u,v,1);
151             bing(u,v);
152         }
153         bool flag = true;
154         int cnt = 0;
155         int s1 = -1, s2 = -1;
156         for(int i = 0;i < 26;i++)
157             if(in[i] || out[i])
158             {
159                 if(find(i) != find(s))
160                 {
161                     flag = false;
162                     break;
163                 }
164                 if((in[i] + out[i])&1)
165                 {
166                     cnt++;
167                     if(s1 == -1)s1 = i;
168                     else s2 = i;
169                 }
170             }
171         if(cnt != 0 && cnt != 2)flag = false;
172         if(!flag)
173         {
174             printf("Case %d: Poor boy!\n",iCase);
175             continue;
176         }
177         if(cnt == 2)
178         {
179             out[s1]++;
180             in[s2]++;
181             addedge(s1,s2,1);
182         }
183         for(int i = 0;i < 26;i++)
184         {
185             if(out[i] - in[i] > 0)
186                 addedge(26,i,(out[i] - in[i])/2);
187             else if(in[i] - out[i] > 0)
188                 addedge(i,27,(in[i] - out[i])/2);
189         }
190         sap(26,27,28);
191         for(int i = head[26];i != -1;i = edge[i].next)
192             if(edge[i].cap > 0 && edge[i].cap > edge[i].flow)
193             {
194                 flag = false;
195                 break;
196             }
197         if(flag)printf("Case %d: Well done!\n",iCase);
198         else printf("Case %d: Poor boy!\n",iCase);
199     }
200     return 0;
201 }

 

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