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
判断是否是欧拉路。需要判断两个方面,一:图是否连通。可以用压缩路径的并查集。二:是否满足度数为奇数的点为0或者只有2个。
下面的做法是不判重的HASH~
44160K | 985MS |
#include <iostream> #include <cstring> #include <string> #include <cstdio> using namespace std; int color[6000000]; int father[6000000]; int Hash(char *s) { int key=0; int len=strlen(s); for(int i=0;i<len;i++) { key=(key*307+s[i])%5235367; } return key; } int find(int x) { if(x==father[x])return x; father[x]=find(father[x]); return father[x]; } void Union(int x,int y) { int xx=find(x); int yy=find(y); father[xx]=yy; } int main() { for(int i=0;i<=5235767;i++) { father[i]=i; } memset(color,0,sizeof(color)); char str1[14],str2[14]; while(scanf("%s%s",str1,str2)==2) { int h1=Hash(str1); int h2=Hash(str2); color[h1]++;color[h2]++; Union(h1,h2); } int sum=0; int zuzong;bool flag; for(int i=0;i<=5235367;i++) { if(color[i]&1) { sum++; if(sum>=3)goto L; } } for(int i=0;i<=5235367;i++) { if(color[i]) { zuzong=find(i); break; } } flag=true; for(int i=0;i<=5235367;i++) { if(color[i]&&find(i)!=zuzong) { flag=false; goto L; } } L: if(flag&&(sum==0||sum==2)) { printf("Possible\n"); } else printf("Impossible\n"); }
判重的哈希:
27548K 1625MS
#include <iostream> #include <cstdio> #include <cstring> #include <vector> using namespace std; struct Word { int sum;//出现的次数 char str[12]; int id;//这是第几种单词。并查集的时候要用到 }word[500008]; #define maxn 106541 vector <Word> ans[maxn+1]; int father[500008]; int Hash(char *s) { int key=0,len=strlen(s); for(int i=0;i<len;i++) { key=(key*307+s[i])%106541; } return key; } int find(int x) { if(x==father[x])return x; father[x]=find(father[x]); return father[x]; } void Union(int x,int y) { int xx=find(x); int yy=find(y); father[xx]=yy; } int main() { int zuzong;bool liantong; for(int i=0;i<=500008;i++) { father[i]=i; } int k=0,t=0; while(scanf("%s%s",word[k].str,word[k+1].str)==2) { int h1=Hash(word[k].str); int h2=Hash(word[k+1].str); if(!ans[h1].size()) { ans[h1].push_back(word[k]); word[k].id=t; ans[h1][0].id=t++; ans[h1][0].sum=1; } else { bool flag=false; for(int i=0;i<ans[h1].size();i++) { if(strcmp(ans[h1][i].str,word[k].str)==0) { ans[h1][i].sum++; word[k].id=ans[h1][i].id; flag=true; break; } } if(!flag) { ans[h1].push_back(word[k]); word[k].id=t; ans[h1][ans[h1].size()-1].id=t++; ans[h1][ans[h1].size()-1].sum=1; } } if(!ans[h2].size()) { ans[h2].push_back(word[k+1]); ans[h2][0].sum=1; word[k+1].id=t; ans[h2][0].id=t++; } else { bool flag=false; for(int i=0;i<ans[h2].size();i++) { if(strcmp(ans[h2][i].str,word[k+1].str)==0) { ans[h2][i].sum++; word[k+1].id=ans[h2][i].id; flag=true; break; } } if(!flag) { ans[h2].push_back(word[k+1]); word[k+1].id=t; ans[h2][ans[h2].size()-1].sum=1; ans[h2][ans[h2].size()-1].id=t++; } } k+=2; } int jidu=0; for(int i=0;i<maxn;i++) { if(ans[i].size()) { for(int j=0;j<ans[i].size();j++) { if(ans[i][j].sum&1) { jidu++; if(jidu>=3)goto L; } } } } for(int i=0;i<k;i+=2) { Union(word[i].id,word[i+1].id); } liantong=true; zuzong=find(0); for(int i=0;i<t;i++) { if(find(i)!=zuzong) { liantong=false; goto L; } } L: if((jidu>=3||jidu==1)||!liantong) { printf("Impossible\n"); } else printf("Possible\n"); }
Tire树:
59060K 516MS
/* 欧拉路径问题 */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; #define maxn 5000800 #define maxm 500080 int father[maxm],rank1[maxm],du[maxm]; int cnt,ant; struct Node { Node * pr[26]; int id; /*Node() { for(int i = 0;i < 26;i++) pr[i] = NULL; }*/ }*root,memory[maxn]; Node * createnode() { Node * p = &memory[ant++]; for(int i = 0;i < 26;i++) { p -> pr[i] = NULL; } p ->id = 0; return p; } int idx(char c) { return c - 'a'; } int insert(char * s) { int len = strlen(s); Node * p = root; for(int i = 0;i < len;i++) { int u = idx(s[i]); if(p -> pr[u] == NULL) { p -> pr[u] = createnode(); } p = p -> pr[u]; } if(p -> id == 0) { p -> id = cnt++; } return p -> id; } void init(int n) { for(int i = 0;i < n;i++) { father[i] = i; } memset(rank1,0,sizeof(rank1)); memset(du,0,sizeof(du)); } int find(int x) { if(x == father[x]) return x; return father[x] = find(father[x]); } void Union(int a,int b) { int fa = find(a),fb = find(b); if(fa == fb) return; if(rank1[fa] > rank1[fb]) { father[fb] = fa; } else if(rank1[fa] < rank1[fb]) { father[fa] = fb; } else { father[fb] = fa; rank1[fa]++; } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); cnt = 1,ant = 0; char str1[12],str2[12]; init(maxm); root = createnode(); while(scanf("%s%s",str1,str2)!=EOF) { int a = insert(str1); int b = insert(str2); Union(a,b); du[a]++;du[b]++; } int src = find(1); bool flag = true; for(int i = 1;i < cnt;i++) { if(find(i) != src) { flag = false; break; } } //到这里说明连通 int jinum = 0; for(int i = 1;i < cnt;i++) { if(du[i] & 1) jinum++; } if(flag && (jinum == 0 || jinum == 2)) printf("Possible\n"); else printf("Impossible\n"); }
/* 并查集判连通+欧拉回路 */ #include <iostream> #include <cstdio> #include <cstring> using namespace std; #define maxn 5008000 #define maxm 500800 int father[maxm],du[maxm]; int rank1[maxm]; char str1[14],str2[14]; int find(int x) { if(x == father[x]) return x; return father[x] = find(father[x]); } void Union(int a,int b) { int fa = find(a); int fb = find(b); if(fa == fb) return; if(rank1[fa] > rank1[fb]) { father[fb] = fa; } else if(rank1[fa] == rank1[fb]) { father[fb] = fa; rank1[fa]++; } else father[fa] = fb; } struct Trie { int first[maxn],nxt[maxn]; int ch[maxn],val[maxn]; int cnt,index; void init() { index = 0; cnt = 1; val[0] = 0; first[0] = -1; } int insert(char * s) { int u = 0; int len = strlen(s); for(int i = 0;i < len;i++) { int id = s[i]; int j;bool flag = false; for(j = first[u];j != -1;j = nxt[j]) { if(ch[j] == id) { flag = true; break; } } if(!flag) { ch[cnt] = id; val[cnt] = 0; first[cnt] = -1; nxt[cnt] = first[u]; first[u] = cnt++; } if(flag) u = j; else u = cnt-1; } if(!val[u]) val[u] = ++index; return val[u]; } }trie; int main() { //freopen("in.txt","r",stdin); for(int i = 1;i < maxm;i++) { father[i] = i; du[i] = rank1[i] = 0; } trie.init(); while(scanf("%s",str1)!=EOF) { scanf("%s",str2); int a = trie.insert(str1); int b = trie.insert(str2); Union(a,b); du[a]++; du[b]++; } int zuzong = find(1); bool flag = true; for(int i = 1;i <= trie.index;i++) if(find(i) != zuzong) { flag = false; break; } int jinum = 0; for(int i = 1;i <= trie.index;i++) if(du[i] & 1) jinum++; if((jinum == 0 || jinum == 2) && flag) puts("Possible"); else puts("Impossible"); return 0; }