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 }