Colored Sticks
Time Limit: 5000MS | Memory Limit: 128000K | |
Total Submissions: 29235 | Accepted: 7710 |
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
题目意思就是说能不能把每个stick都连接起来成一行(即能不能构成一个欧拉路baike.baidu.com/view/566040.htm?fr=aladdin),能就Possible,反之Impossible。
我原来打算是用map做的,结果超时了,后来打算用哈希函数确定id,结果找不到合适的函数。无奈只能用trie了。
首先用trie确定每种颜色的id,然后确定每种颜色出现次数,欧拉判断一下,再并查集一下就行了。
AC代码:
#include<iostream> #include<map> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int f[1500]; int a[1500]; int trie[510000][26],num[510000][26]; int n,r; int insert(char *ch){ int j=0; while(*ch){ if(trie[j][*ch-'a']) j=trie[j][*ch-'a']; else{ ++r; trie[j][*ch-'a']=r; j=r; } ch++; } ch--; if(!num[j][*ch]) num[j][*ch]=++n; //确定该字符串是第几个字符 return num[j][*ch]; //返回该字符串的id } int find(int x){ //并查集 if(x==f[x]) return x; return f[x]=find(f[x]); } int main(){ //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); memset(a,0,sizeof(a)); memset(trie,0,sizeof(trie)); memset(num,0,sizeof(num)); n=r=0; for(int i=1;i<1500;i++) //初始化并查集 f[i]=i; char s1[15],s2[15]; int x,y; while(scanf("%s%s",s1,s2)!=EOF){ //数据很多,建议用scanf,cin可能超时 x=insert(s1); y=insert(s2); a[x]++; a[y]++; x=find(x); y=find(y); if(x!=y) f[x]=y; } int cnt=0; for(int i=1;i<=n;i++){ if(f[i]==i) cnt++; if(cnt>=2) break; } if(cnt>=2) cout<<"Impossible"<<endl; //并查集判断是否都属于一个集合 else{ int sum=0; for(int i=1;i<=n;i++){ if(a[i]&1) sum++; if(sum>2) break; } if(sum!=0 && sum!=2) //欧拉判断是否构成欧拉路 cout<<"Impossible"<<endl; else cout<<"Possible"<<endl; } return 0; }