POJ - 2513 - Colored Sticks (绝世好题:字典树+欧拉路+并查集)

题目: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 ;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值