题意:
给定一些木棒,木棒两端都涂上颜色,求是否能将所有木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的。
无向欧拉图:不存在或只存在两个奇度顶点
用并查集判断图的连通性 //判断是否只有一个根结点
用Trie或者hash给每种颜色编号
静态数组Trie
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<vector> #include<algorithm> #include<queue> using namespace std; const int maxn = 520000; int du[maxn], f[maxn]; int n; int findset(int x) { return x==f[x]?x:f[x]=findset(f[x]); } //Trie int ch[maxn][26]; int id[maxn]; int sz; int Insert(char s[]) { int u = 0, len = strlen(s); for(int i=0; i<len; ++i) { int c = s[i] - 'a'; if(!ch[u][c]) { memset(ch[sz], 0, sizeof ch[sz] ); id[sz] = 0; ch[u][c] = sz++; } u = ch[u][c]; } if(!id[u]) id[u] = ++n; return id[u]; } void init() { for(int i=0; i<maxn; ++i) { f[i] = i; du[i] = 0; } sz = 1; n = 0; memset(ch[0], 0, sizeof ch[0] ); } int main() { char str1[20], str2[20]; init(); while(~scanf("%s %s", str1, str2)) { int a = Insert(str1); //同时返回编号 int b = Insert(str2); du[a]++; du[b]++; int pa = findset(a); int pb = findset(b); if(pa != pb) { f[pa] = pb; } } int cnt_root = 0; for(int i=1; i<=n; ++i){ if(f[i]==i){ if(++cnt_root>1){ puts("Impossible"); return 0; } } } int oddn = 0; for(int i=1; i<=n; ++i) { if(du[i]&1) oddn++; } if(oddn==0 || oddn==2) { puts("Possible"); } else { puts("Impossible"); } return 0; }
//Trie int head[maxn]; int next[maxn]; char ch[maxn]; int id[maxn]; int sz; int Insert(char s[]) { int u = 0, v, len = strlen(s); for(int i=0; i<len; ++i) { bool flag = false; for(v = head[u]; v!=0; v=next[v]) if(ch[v]==s[i]) { flag = true; break; } if(!flag) { v = sz++; ch[v] = s[i]; next[v] = head[u]; head[u] = v; head[v] = 0; } u = v; } if(!id[u]) id[u] = ++n; return id[u]; } void init() { for(int i=0; i<maxn; ++i) { f[i] = i; du[i] = 0; } sz = 1; head[0] = next[0] = 0; n = 0; } int main() { char str1[20], str2[20]; init(); while(~scanf("%s %s", str1, str2)) { int a = Insert(str1); //同时返回编号 int b = Insert(str2); du[a]++; du[b]++; int pa = findset(a); int pb = findset(b); if(pa != pb) { f[pa] = pb; } } int cnt_root = 0; for(int i=1; i<=n; ++i){ if(f[i]==i){ if(++cnt_root>1){ puts("Impossible"); return 0; } } } int oddn = 0; for(int i=1; i<=n; ++i) { if(du[i]&1) oddn++; } if(oddn==0 || oddn==2) { puts("Possible"); } else { puts("Impossible"); } return 0; }
hash
#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<vector> #include<algorithm> #include<queue> using namespace std; const int maxn = 251000; int du[maxn], f[maxn]; int n; int findset(int x) { return x==f[x]?x:f[x]=findset(f[x]); } void Union(int a, int b) { if(f[a]==-1) f[a] = a; if(f[b]==-1) f[b] = b; int pa = findset(f[a]); int pb = findset(f[b]); if(pa!=pb) f[pa] = pb; } // BKDR Hash Function int Hash(char str[]) { unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. unsigned int hash = 0; while (*str) { hash = hash * seed + (*str++); } return (hash & 0x7FFFFFFF) % maxn; } int main() { char str1[20], str2[20]; memset(du, 0, sizeof du ); memset(f, -1, sizeof f ); while(~scanf("%s %s", str1, str2)) { int a = Hash(str1); int b = Hash(str2); du[a]++; du[b]++; Union(a, b); } int cnt_root = 0; for(int i=1; i<maxn; ++i) { if(f[i]!=-1) { if(f[i]==i) cnt_root++; } } if(cnt_root >1) { puts("Impossible"); return 0; } int oddn = 0; for(int i=1; i<maxn; ++i) { if(f[i]!=-1 && du[i]&1) oddn++; } if(oddn==0 || oddn==2) { puts("Possible"); } else { puts("Impossible"); } return 0; }