POJ-2513 Colored Sticks
题目大意:
给定一捆木棍,每根木棍的每个端点涂有某种颜色。问你是否能将这些棍子首尾相连,排成一条直线,且相邻两根棍子的连接处端点的颜色一样
解题思路:
应该可以说是判断欧拉路径的裸题了
不过有些地方很蛋疼= =我一开始写的是vector+string+map用了三个STL模板写的,结果TLE
所以这道题我比较推荐用Trie(字典树) + 并查集来处理,相对来说比较稳
以及玛德这道题为什么有菊苣能写到16ms并且内存也只用了652K
代码:
#include <cstdio> #include <cstring> using namespace std; typedef struct node{ int num; node *next[26]; }Trie; const int maxn = 250000 * 2 + 10; int tot, pre[maxn], deg[maxn]; Trie *init(Trie *rt){ rt -> num = 0; for(int i = 0; i < 26; ++i) rt -> next[i] = NULL; return rt; } Trie *createTrie(Trie *rt, char *s){ Trie *p = rt; int v, len = strlen(s); for(int i = 0; i < len; ++i){ v = s[i] - 'a'; if(p -> next[v] == NULL){ p -> next[v] = new Trie; p = p -> next[v]; p = init(p); p -> num = 0; }else p = p -> next[v]; } p -> num = tot++; return rt; } int getNum(Trie *rt, char *s){ Trie *p = rt; int v, len = strlen(s); for(int i = 0; i < len; ++i){ v = s[i] - 'a'; if(p -> next[v] == NULL) return 0; else p = p -> next[v]; } return p -> num; } void clearTrie(Trie *t){ if(t == NULL) return; for(int i = 0; i < 26; ++i){ clearTrie(t -> next[i]); } delete t; } int findfather(int x){ return pre[x] = (pre[x] == x ? x : findfather(pre[x])); } int judge(){ int tmp = findfather(1); for(int i = 2; i < tot; ++i){ if(findfather(i) != tmp) return 0; } return 1; } int main(){ tot = 1; int a, b; Trie *t; t = new Trie; t = init(t); char color1[12] = {0}, color2[12] = {0}; for(int i = 0; i < maxn; ++i) pre[i] = i, deg[i] = 0; while(~scanf(" %s %s", color1, color2)){ if(getNum(t, color1) == 0) t = createTrie(t, color1); if(getNum(t, color2) == 0) t = createTrie(t, color2); a = getNum(t, color1); b = getNum(t, color2); ++deg[a]; ++deg[b]; pre[findfather(a)] = findfather(b); } int flag = 0; for(int i = 1; i < tot; ++i){ flag += deg[i] & 1; } if(flag == 0 || flag == 2) flag = judge(); else flag = 0; if(flag) puts("Possible"); else puts("Impossible"); clearTrie(t); return 0; }