原题传送:http://poj.org/problem?id=2513
字典树 + 并查集 + 欧拉路。
字典树:相当于hash的功能
并查集:判断连通
欧拉路:求答案
要存在欧拉路就要满足:
1.该图必须是一个连通图
2.该图每个点的度数要么全为偶数,要么有且仅有两个点的度数为奇数
View Code
1 #include <stdio.h> 2 #include <string.h> 3 #include <queue> 4 #define N 500005 5 using namespace std; 6 7 int k, f[N],g[N]; 8 char a[15], b[15]; 9 10 struct trie 11 { 12 int id; 13 trie *next[26]; 14 trie() 15 { 16 id = 0; 17 memset(next, 0, sizeof next); 18 } 19 }; 20 21 int insert(trie *root, char s[]) 22 { 23 trie *cur = root; 24 for(int i = 0; s[i]; i ++) 25 { 26 int m = s[i] - 'a'; 27 if(cur->next[m] == NULL) 28 { 29 cur->next[m] = new trie(); 30 } 31 cur = cur->next[m]; 32 } 33 if(cur->id == 0) 34 cur->id = k ++; 35 return cur->id; 36 } 37 38 int find(int x) 39 { 40 return f[x] == x ? f[x] : f[x] = find(f[x]); 41 } 42 43 void union_set(int x, int y) 44 { 45 int u = find(x); 46 int v = find(y); 47 f[v] = u; 48 } 49 50 void init() 51 { 52 k = 1; 53 for(int i = 1; i < N; i ++) 54 f[i] = i; 55 } 56 57 int main() 58 { 59 int i; 60 trie *root = new trie(); 61 init(); 62 while(scanf("%s%s", a, b) != EOF) 63 { 64 int x = insert(root, a); 65 int y = insert(root, b); 66 union_set(x, y); 67 g[x] ++, g[y] ++; 68 } 69 int v = find(1); 70 for(i = 2; i < k; i ++) 71 { 72 if(find(i) != v) 73 break; 74 } 75 if(i < k) 76 puts("Impossible"); 77 else 78 { 79 int cnt = 0; 80 for(i = 1; i < k ; i ++) 81 { 82 if(g[i] & 1) 83 cnt ++; 84 } 85 if(cnt == 0 || cnt == 2) 86 puts("Possible"); 87 else 88 puts("Impossible"); 89 } 90 return 0; 91 }
程序跑了1300+ms,对于5000ms的时限来说还是合理的。
如果追求更快,那么搞IO加速、循环跳出或静态字典树都能省不少时间,但总体思路还是一样的。