题目链接:
题意:
给定一捆木棍。每根木棍的每个端点涂有某种颜色。问:是否能将这些棍子首尾相连,排成
一条直线,且相邻两根棍子的连接处端点的颜色一样。
输入描述:
输入文件中包含若干行,每行为两个单词,用空格隔开,表示一根棍子两个端点的颜色。表
示颜色的单词由小写字母组成,长度不超过10 个字符。木棍的数目不超过250000。
输出描述:
如果木棍能按照题目的要求排成一条直线,输出"Possible",否则输出"Impossible"。
解题思路:
判断能否排成一条直线,可将木棍理解为一条无向边,然后保存所有颜色点的度数,判断该图是否连通且是否构成欧拉路
题目没有给出颜色种类的最大值,所以要确定每种颜色的标号需要一种特殊的hash方法:字典树。
代码:
#include<iostream> #include<cstdio> #include<cstring> #define M 530000 using namespace std; struct node { int Id; node* next[26]; node() { Id=-1; for(int i=0; i<26; i++) next[i]=NULL; } }*Root; int fa[M]; int degree[M]; int num; int U_find(int x) { return x==fa[x]?x:fa[x]=U_find(fa[x]); } int trie_find(char str[]) { node* p=Root; int len=strlen(str); for(int i=0; i<len; i++) { if(p->next[str[i]-'a']==NULL) p->next[str[i]-'a']=new node(); p=p->next[str[i]-'a']; } if(p->Id==-1) p->Id=num++; return p->Id; } int main() { Root=new node(); num=0; for(int i=0; i<M; i++) { fa[i]=i; degree[i]=0; } char str1[12],str2[12]; int Id1,Id2; while(~scanf("%s%s",str1,str2)) { Id1=trie_find(str1); Id2=trie_find(str2); fa[U_find(Id1)]=U_find(Id2); degree[Id1]++; degree[Id2]++; } int s=0,Ancestor=0; for(int i=0; i<num; i++) { if(U_find(i)==i) Ancestor++; if(degree[i]%2==1) s++; } if(num==0) //没有数据也是"Possible" cout<<"Possible"<<endl; else if(Ancestor==1&&(s==0||s==2)) cout<<"Possible"<<endl; else cout<<"Impossible"<<endl; return 0; }
时间: 2024-09-28 23:08:20