题目:POJ - 2513
题意:一些木棒,两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的。
思路 : 这个题的话就比较麻烦,不过倒也好理解,有并查集,字典树来保存字符串集合,用图论(欧拉路)知识来解决就可以了,这个题如果把木棒看成一条边,木棒一端具有相同颜色的看成同一个点,因此可以转化成一个图中判断能否一笔画,就是给你一个无向图,让你判断是否存在欧拉路。而无向图中存在欧拉路的的条件有两个,一个是图要是联通的,二是所有节点的度为偶数度,或者奇数度节点为偶数个,其实就是两个。(字典树用来储存单词,每个单词对应一个节点,用并查集把每个点合并在一起,然后再用欧拉路知识判断是否存在欧拉路)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#define N 500005
using namespace std;
int tot=0,cnt=0,k;
int deg[N],f[N];
struct ljh
{
int num;
int nex[27];
}e[N];
int Insert(char c[])//字典树的建树
{
int len=strlen(c),p=0;
for(int i=0;i<len;i++)
{
char t=c[i]-'a';
if(e[p].nex[t]==0)
{
// memset(e[p],0,sizeof(e[p]));
e[p].nex[t]=++tot;
e[p].num=0;
}
p=e[p].nex[t];
}
if(e[p].num==0)e[p].num=++cnt;//如果是一个新的单词
return e[p].num;
}
void init()
{
memset(deg,0,sizeof(deg));
for(int i=1;i<=N;i++)f[i]=i;
}
int find(int x)//并查集
{
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
void merge(int x,int y)
{
int u=find(x);
int v=find(y);
if(u!=v)f[u]=v;
}
int main()
{
init();
char a[15],b[15];
while(~scanf("%s %s",a,b))
{
int id1=Insert(a);
int id2=Insert(b);
deg[id1]++;
deg[id2]++;//出现次数
merge(id1,id2);
}
int k=0;
for(int i=1;i<=cnt;i++)//其实就是判断是否存在欧拉路
{
if(deg[i]%2==1)k++;//出现次数为奇数
if(k>2||find(1)!=find(i))//说明全在一个集合内
{
printf("Impossible\n");
return 0 ;
}
}
if(k==1)printf("Impossible\n");
else printf("Possible\n") ;
return 0 ;
}