题目链接:http://poj.org/problem?id=2513
题目大意:你有好多根棍子,这些棍子的两端分都别涂了一种颜色。请问你手中的这些棍子能否互相拼接,从而形成一条直线呢?
两根棍子只有在颜色相同的时候才能拼接。比如有两根棍子,第一根棍子的两端的颜色分别为blue green,第二根两端的颜色为blue red,那么他们就可以拼接成green blue blue red或者red blue blue green。
解题思路:跟之前写的POJ1386很像,都是首尾连通。但是这里需要用字典树(不能用map会超时)对这些颜色单词做处理分配编号,然后这些颜色就是一个个节点了,就可以建图了,然后判断一下是不是欧拉回(通)路即可。注意,这里的木棍可以反转,所以是无向图,还有输入的字符串数目可能为0要特判一下输出“Possible”。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define CLR(arr,val) memset(arr,val,sizeof(arr))
using namespace std;
const int M=5e5+; struct Tire{
Tire *next[];
int flag;
Tire(){
for(int i=;i<;i++)
next[i]=NULL;
flag=-;
}
};
int degree[M],fa[M],color; int Insert(char *str,Tire *&root){//要插入的字符串str
Tire *p=root;
for(int i=;str[i]!='\0';i++){
int k=str[i]-'a';
if(p->next[k]==NULL)
p->next[k]=new Tire;
p=p->next[k];
}
if(p->flag==-)
p->flag=++color;
return p->flag;
} void del(Tire *root){ //动态建树后要释放内存
for(int i=;i<;i++)
if(root->next[i])
del(root->next[i]);
delete(root);
} int find(int x){
return fa[x]==x?x:fa[x]=find(fa[x]);
} int main(){
char str1[],str2[];
Tire *root=new Tire;
for(int i=;i<M;i++){
fa[i]=i;
}
while(~scanf("%s%s",str1,str2)){
int u,v;
u=Insert(str1,root);
v=Insert(str2,root);
degree[u]++;
degree[v]++;
if(find(u)!=find(v))
fa[find(u)]=find(v);
}
del(root);
bool flag=true;
int cnt1=,cnt2=,chu,ru;
for(int i=;i<=color;i++){
if(find(i)==i)
cnt1++;
if(degree[i]%==)
cnt2++;
}
//注意有字符串为0的情况,还有这是无向图
if((cnt1==||cnt1==)&&(cnt2==||cnt2==))
puts("Possible");
else
puts("Impossible");
return ;
}