POJ 2513 Colored Sticks 字典树 + 并查集 + 欧拉通路
比赛那天下午做的。。。比赛的时候真不知道怎么做。。。亏了没做,做了我就死了。。欧拉回路我是真心不会判断啊(真的是忘了)。。。虽然离散考了86(鼓掌~),也不过是全班最高(再次鼓掌~)但是真的是恶补出来的(天赋秉异,美女上台献花)
不扯淡了。。。这道题因为数据量比较大。。。500000的数据,所以用map和平常的查找肯定会TLE所以,要用到TRIE树。
然后欧拉通路的判定就是通过查找度数为奇数的节点 < 2 是否成立不成立肯定是错的,但是成立了也要判断是不是父节点是否为一个节点。比如
red red
blue blue
答案就是impossible
代码如下
View Code
1 #include <stdio.h> 2 #include <string.h> 3 struct node 4 { 5 int count; 6 int next[27]; 7 }word[250050*4]; 8 int num = -1; 9 int count = 0; 10 int set[500050]; 11 int b[500050]; 12 13 void new_node()//新建节点 14 { 15 num++; 16 word[num].count = 0; 17 for(int i = 0;i < 27;i++) 18 word[num].next[i] = -1; 19 20 } 21 int insert(char *s,struct node word[]) 22 { 23 int i,dic; 24 for(i = 0,dic = 0;s[i] != '\0';i++) 25 { 26 if(word[dic].next[s[i]-'a'] == -1) 27 { 28 new_node(); 29 word[dic].next[s[i]-'a'] = num; 30 } 31 dic = word[dic].next[s[i]-'a']; 32 33 } 34 word[dic].count++; 35 if(word[dic].count == 1) 36 b[count++] = dic; 37 38 39 return dic; 40 } 41 int find(int i)//此处最好用这种递归 42 { 43 if(set[i] != i) 44 set[i] = find(set[i]); 45 return set[i]; 46 } 47 void merge(int x,int y) 48 { 49 int fx = find(x); 50 int fy = find(y); 51 if(x != y) 52 { 53 set[fx] = fy; 54 } 55 } 56 int main() 57 { 58 59 char s1[20],s2[20]; 60 61 int i; 62 for(i = 0;i < 510005;i++) 63 set[i] = i; 64 new_node(); 65 while(~scanf("%s %s",s1,s2)) 66 { 67 int x1,x2; 68 x1 = insert(s1,word); 69 x2 = insert(s2,word); 70 merge(x1,x2); 71 72 73 } 74 int leap = 0,tag = 1; 75 for(i = 0;i < count;i++) 76 { 77 if(word[b[i]].count%2)//度数为奇的节点数是否小于2 78 leap++; 79 if(leap > 2) 80 { 81 tag = 0; 82 break; 83 84 } 85 } 86 if(tag) 87 { 88 int par; 89 par = find(set[b[0]]); 90 for(i = 0;i < count;i++) 91 { 92 int temp = find(set[b[i]]);//一定要超找一下,千万不要直接用set[b[i]] 93 if(temp != par) 94 { 95 tag = 0; 96 break; 97 } 98 99 } 100 } 101 if(tag) 102 puts("Possible"); 103 else 104 puts("Impossible"); 105 106 return 0; 107 }