题意:
有一捆木棍,首尾都有颜色。如果一根木棍的首部颜色 与 另一根木棍的尾部颜色相同那么这两根木棍就可以连在一起,求所有的木棍是否可以连成一根
思路:
重点是 判断是否存在欧拉通路。如果存在欧拉通路:1、所有的点都在一个集合,2、只有两个或0个度数为奇数的点
注意输入为空的情况
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e6+10;
int tr[maxn][26],pre[maxn],d[maxn];
int tot;
bool v[maxn]; //标记节点为单词
int find(int x)
{
return pre[x]==x?x:find(pre[x]);
}
int insert(char *str)
{
int len = strlen(str);
int root = 0; //根节点编号为0
for(int i=0;i<len;i++)
{
int id = str[i]-'a'; //0~25
if(!tr[root][id]) //如果之前没有从root到id的前缀
tr[root][id] = ++tot; //插入,tot即为第一种编号
root = tr[root][id]; //顺着字典树往下走
}
v[root] = true; //将从0到root点为一个单词
return root;
}
int main()
{
char str1[100],str2[100];
for(int i=1;i<maxn;i++)
pre[i] = i;
while(~scanf("%s %s",str1,str2))
{
int x = insert(str1);
int y = insert(str2);
d[x]++;
d[y]++;
int xx = find(x);
int yy = find(y);
if(xx!=yy)
pre[yy] = xx;
}
int ans = 0;//奇度点个数
int cnt = 0; //几个集合
for(int i=1;i<tot;i++)
{
if(d[i]%2)
ans++;
if(find(i)==i && v[i])
cnt++;
}
if(!(ans==2 || ans==0) || cnt>1) //输入为空时 cnt=0
printf("Impossible\n");
else
printf("Possible\n");
return 0;
}