Colored Sticks(poj 2513) 是一道关于字典树的题,虽然并不是很难,但是要注意很多细节!
题目
Colored Sticks
Time Limit: 5000MS | Memory Limit: 128000K | |
Total Submissions: 35571 | Accepted: 9319 |
Description
You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sticks in a straight line such that the colors of the endpoints that touch are of the same color?
Input
Input is a sequence of lines, each line contains two words, separated by spaces, giving the colors of the endpoints of one stick. A word is a sequence of lowercase letters no longer than 10 characters. There is no more than 250000 sticks.
Output
If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible.
Sample Input
blue red
red violet cyan blue blue magenta magenta cyan
Sample Output
Possible
大致题意就是有一堆小木棍,要将这些小木棍连成一条直线,但是每个小木棍两边都有颜色,只有颜色相同的两端才能连在一起,如果可以就输出“Possible”, 否则输出“Impossible”。具体做法就是首先用字典树把每种出现过的颜色与及出现次数,同时还要用并查集查一下是否所有的点联通,最后再判断是否存在欧拉路(如果一根木棍两端的颜色相同记录一下,因为如果一种颜色出现的次数刚好等于两端都是这种颜色的木棍数的两倍是不存在欧拉路的,要特判一下)。以下是代码:
Memory: 73892K | Time: 1422MS |
<span style="font-size:14px;">#include <iostream> #include <cstdio> #include <string.h> #include <cstdlib> using namespace std; struct node { int k; struct node *next[26]; node() { k = 0; for(int i = 0; i < 26; i ++) next[i] = NULL; } }; int num = 0, flag[500007], d[500007], lian[500007]; int Build_or_Find( struct node *t, char s[]) // 字典树存点 { int temp; for( int i = 0; s[i] != '\0'; i ++) { temp = s[i] - 'a'; if( t->next[temp] == NULL) t->next[temp] = new node; t = t->next[temp]; } if(!t->k) t->k = ++ num; d[t->k] ++; return t->k; } bool cmp() //判断是否存在欧拉路与及是否所有的的点都联通 { int sum = 0, need = 0; for( int i = 1; i <= num; i ++) // 判断联通 if( lian[i] == i) need ++; if(need > 1) return false; for( int i = 1; i <= num; i ++) // 判断欧拉路 { if( flag[i] * 2 == d[i]) // 特判一下</span><span style="font-size:12px; font-family: 'Courier New', Courier, monospace;">一种颜色出现的次数刚好等于两端都是这种颜色的木棍数的两倍,是就返回FALSE</span>
<span style="font-size:14px;"> return false; if(d[i]&1) { sum ++; if(sum > 2) return false; } } return true; } int Find( int key) //并查集查找函数 { int z = key; while(z != lian[z]) z = lian[z]; int j = key, s; while(j != z)// 压缩路径 { s = lian[j]; lian[j] = z; j = s; } return z; } int main() { int p, q, u, v; char a[12], b[12]; struct node *head; head = new node; for( int i = 1; i <= 500000; i ++) lian[i] = i; while(scanf("%s", a)!=EOF) { scanf("%s", b); p = Build_or_Find( head, a); q = Build_or_Find( head, b); if(p == q)// 记录两端为同一种颜色的木棍数 { flag[p] ++; continue; } u = Find(p); v = Find(q); if(u != v) lian[u] = v; } if(cmp()) printf("Possible\n"); else printf("Impossible\n"); return 0; }</span>