一道有关 字典树的题,,我感觉图论用的更多一些,
题意:
给你 多根棍子,每根棍子前后各有一种颜色,只有颜色相同才能拼在一起,问能不能结成一根棍子
首先 ,这道题我们需要两点注意,一是能不能把这些节点连在一起,二是能不能形成一个 欧拉回路(如果能围成一个圈自然能连成一条线)
但是对于如何实现记录 就依靠字典树的根节点来实现,设立一个拜访数组记录最后一个点是第几个节点,再设立一个计数数组,统计是每个颜色出现次数,观察是否是欧拉回路。
以下是 AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 2e6+5;
int tree[maxn][30];
int flag[maxn];
int pre[maxn];
int vis[maxn];
int sum[maxn];
int tot,cnt;
int _insert(char *str)
{
int rt=0;
int len = strlen(str);
for(int i=0; i<len; i++)
{
int id = str[i] - 'a';
if(!tree[rt][id])
tree[rt][id]=++tot;
rt = tree[rt][id];
}
if(!vis[rt])
vis[rt]=++cnt;
if(pre[cnt]==0)
pre[cnt]=cnt;
return vis[rt];
}
int findd(int x)
{
return pre[x]==x?x:pre[x]=findd(pre[x]);
}
void unite(int x,int y)
{
int fx=findd(x),fy=findd(y);
if(fx!=fy)
pre[fy]=fx;
}
char s1[30],s2[30];
int main()
{
tot=0,cnt=0;
memset(vis,0,sizeof(vis));
memset(pre,0,sizeof(pre));
memset(sum,0,sizeof(sum));
while(scanf("%s%s",s1,s2)!=EOF)
{
int pos1,pos2;
pos1 = _insert(s1);
pos2 = _insert(s2);
sum[pos1]++,sum[pos2]++;
unite(pos1,pos2);
}
int flag=0;
for(int i=1;i<=cnt;i++)
{
if(sum[i]%2==1)
{
flag++;
}
if(findd(i)!=findd(1))
{
printf("Impossible\n");
return 0;
}
}
if(flag==0||flag==2)
printf("Possible\n");
else
printf("Impossible\n");
return 0;
}