题意:很多棒棒,首位有颜色,如果一个棒棒的首颜色和另一个棒棒的尾颜色相同,则可以连接在一起,问所以棒棒能否连成一线。
个人心得:通过这题学习了欧拉路,知道了用Trie把字符串映射成数字。
思路:把颜色看作节点,把棒看成边,图就建完了,之后看是否在一个连通图中,这里用并查集实现,如果在,再判断是否构成欧拉路,是就也能了。
欧拉路条件:图连通并且入度为奇数的点只有0个或2个。
Trie树映射,不会的可以学习下,据说map很慢。
吐槽:各自变量什么的都开大点,不然RE。。。。。。。。
吐槽(与本题无关):今天出去做题,被各种大牛虐的很惨,心情很不爽,励志要发愤涂墙!。。。。。。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
struct node
{
int c[27];
int id;
}t[5000000];
int num,tnum,in[550005];
int f[550005];
int trie(char *a)
{
int l=strlen(a);
int p=0;
for(int i=0;i<l;i++)
{
if(t[p].c[a[i]-'a']==0)
{
t[p].c[a[i]-'a']=++tnum;
memset(t[tnum].c,0,sizeof(t[tnum].c));
p=tnum;
t[p].id=0;
}
else
{
p=t[p].c[a[i]-'a'];
}
}
if(t[p].id==0)
{
t[p].id=++num;
f[num]=num;
}
return t[p].id;
}
int find(int i)
{
if(f[i]==i)return i;
f[i]=find(f[i]);
return f[i];
}
void un(int u,int v)
{
int x=find(u);
int y=find(v);
if(x<y)f[y]=x;
else f[x]=y;
}
int main()
{
num=0;
tnum=0;
memset(in,0,sizeof(in));
char a[30],b[30];
memset(t[0].c,0,sizeof(t[0].c));
while(scanf("%s%s",a,b)!=EOF)
{
int u=trie(a);
int v=trie(b);
un(u,v);
in[u]++;
in[v]++;
}
int flag=0;
int oddnum=0;
for(int i=1;i<=num;i++)
{
if(f[i]!=f[1])
{
flag=1;
break;
}
if(in[i]%2==1)oddnum++;
}
if(flag)cout<<"Impossible"<<endl;
else if(oddnum==0||oddnum==2)cout<<"Possible"<<endl;
else cout<<"Impossible"<<endl;
return 0;
}