题目: 彩色棒
时间限制:1000 ms | 内存限制:128000 KB
难度:5
描述
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?
输入
the frist line have a number k(0< k<=10),that is the number of case. each case contais a number m,then have m line, 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 13 characters. There is no more than 250000 sticks.
输出
If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible.
样例输入
1
5
blue red
red violet
cyan blue
blue magenta
magenta cyan
样例输出
Possible
分析:
这题是个典型的判断欧拉通路的问题。但是有几点要注意:
1:整个图要是连通的。我们用并查集解决
2:我们要将不同的颜色用不同的数字表示。由于棒的数量很大,不用map()我们用字典树解决。
3:满足欧拉通路的条件。记录顶点度数即可。
AC代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=500010;
int p[maxn],d[maxn];
int id;
struct node
{
node* next[26];
int num;
node()
{
for(int i=0;i<26;i++)
next[i]=NULL;
num=-1;
}
};
int Trie(node * root, char* s)
{
node* p=root;
while(s[0]!='\0')
{
if(p->next[s[0]-'a']==NULL)
{
node* t=new node();
p->next[s[0]-'a']=t;
p=t;
}
else p=p->next[s[0]-'a'];
s++;
}
if(p->num==-1)
p->num=id++;
return p->num;
}
void dfs(node* root)
{
if(root==NULL) return ;
for(int i=0;i<26;i++)
{
if(root->next[i]!=NULL)
{
dfs(root->next[i]);
}
}
free(root);
}
int find(int x)
{
return p[x]==-1?x:p[x]=find(p[x]);
}
void unit(int x,int y)
{
int xx=find(x);
int yy=find(y);
if(xx!=yy)
p[xx]=yy;
}
int main()
{
int t,n;
scanf("%d",&t);
while(t--)
{
char s1[15],s2[15];
id=0;
node* r = new node();
memset(p,-1,sizeof(p));
memset(d,0,sizeof(d));
scanf("%d",&n);
getchar();
if(n==0)
{
printf("Possible\n");continue;
}
int a,b;
for(int i=0;i<n;i++)
{
scanf("%s %s",s1,s2);
a=Trie(r,s1);b=Trie(r,s2);
d[a]++;d[b]++;
unit(a,b);
}
dfs(r);
bool flag=true;
int k=find(0);
for(int i=0;i<id;i++)
{
if(k!=find(i))
{
flag=false;break;
}
}
if(!flag)
{
printf("Impossible\n");continue;
}
int num=0;
for(int i=0;i<id;i++)
{
if(d[i]%2==1)
num++;
if(num>2)
break;
}
if(num==0 || num==2)
printf("Possible\n");
else printf("Impossible\n");
}
return 0;
}