题目意思:有许多的棍子,每一个棍子的两个端点都标记一种颜色, 端点颜色相同的两个棍子可以连在一起,问最后能不能把所有的棍子连成一条直线。。
刚开始题目理解错误,,误以为最后连成一个环,怎样搞都不对,,后来用有道才发现理解错误,,英语差的真的伤不起啊。。。
先用Trie树把颜色改为点,并记录每一种颜色出现的次数,再用并查集判断是否连通,,之后用欧拉回路判断能否构成直线。。
这里存在两种情况:
1-3 , 3-5, 5-1 和 1-3 , 3-5, 5-1 , 1-2
一种是所有的所有的颜色都出现偶数次,
另一种是有两种颜色出现奇数次,, 这样就很简单了。。
# include<stdio.h>
# include<string.h>
# define N 250005
# define MAX 26
struct Trie{
int num,xuhao;
struct Trie *next[MAX];
};
int t,adj[2*N],father[2*N];
Trie *NewTrie()
{
Trie *temp=new Trie;;
int i;
temp->num=0;
for(i=0;i<MAX;i++)
temp->next[i]=NULL;
return temp;
}
int updata(Trie *p,char s[])
{
int len,i;
Trie *temp=p;
len=strlen(s);
for(i=0;i<len;i++)
{
if(temp->next[s[i]-'a']==NULL) temp->next[s[i]-'a']=NewTrie();
temp=temp->next[s[i]-'a'];
}
temp->num++;
if(temp->num==1) {t++;temp->xuhao=t;adj[t]=1;}
else adj[temp->xuhao]++;
return temp->xuhao;
}
int find(int x)
{
while(father[x]!=x)
x=father[x];
return x;
}
void Union(int a,int b)
{
int x,y,min;
x=find(a);
y=find(b);
min=x<y?x:y;
father[x]=father[y]=father[a]=father[b]=min;
}
int main()
{
int i,count,flag,a,b;
char s1[15],s2[15];
Trie *p;
p=NewTrie();
t=0;
for(i=0;i<2*N;i++)
father[i]=i;
while(scanf("%s%s",s1,s2)!=EOF)
{
a=updata(p,s1);
b=updata(p,s2);
Union(a,b);
}
count=0;
flag=0;
for(i=1;i<=t;i++)
{
if(father[i]!=1) {flag=1;break;}
if(adj[i]%2!=0) count++;
if(count>=3) {flag=1;break;}
}
if(flag==1) printf("Impossible\n");
else printf("Possible\n");
return 0;
}