题目大意:
给定一捆木棍,每根木棍的每个端点涂有某种颜色。问你是否能将这些棍子首尾相连,排成一条直线,且相邻两根棍子的连接处端点的颜色一样
解题思路:
应该可以说是判断欧拉路径的裸题了
不过有些地方很蛋疼= =我一开始写的是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;
}