POJ 2513 Colored Sticks (欧拉回路 + 并查集 + 字典树)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/PK__PK/article/details/82782101

题目链接:http://poj.org/problem?id=2513

题意:有n段木头,每段木头的两端都有颜色。相同颜色的木头能拼接在一起成为一段。问是否能把所有木头拼接在一起。成为一段。

题解:这道题,和刘汝佳的紫书上的一道题欧拉回路的题目很像,据说这道题map映射会超时,所以映射就用字典树来代替。那么这道题的思路就可以变成,每个木头分成两段,然后每个端点的颜色hash成一个点。连接之后判断欧拉回路。并用并查集判断连通性。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 5e5 + 5;
int pre[maxn];
int in[maxn];
int digit;

struct len{
	int num;
	int flag;
	struct len *next[27];
	len(){
		flag = 0 ;
		memset(next,0,sizeof(next));
	}
}root;
int insert(char *s){
	struct len *p = &root;
	int length = strlen(s);
	for(int i = 0 ; i < length ; i ++){
		int index = s[i] -'a';
		if(p->next[index] == NULL){
			p->next[index] = new struct len;
		}
		p = p->next[index];
	}
	if(p->flag != 1){
		p->flag = 1;
		p->num = digit ++;
		return p->num;
	}
	else return p->num;
}

int find(int x){
	return pre[x] = (x == pre[x] ? x : find(pre[x]));
}

void add(int x,int y){
	int fx = find(x);
	int fy = find(y);
	if(fx != fy){
		pre[fx] = fy;
	}
}
int main(){
	for(int i = 1 ; i < maxn ; i ++)
		pre[i] = i;
	char s1[15],s2[15];
	digit = 0;
	memset(in,0,sizeof(in));
	while(scanf("%s%s",s1,s2) != EOF){
		int t1 = insert(s1),t2 = insert(s2);
		add(t1,t2);
		in[t1]++;
		in[t2]++;
	}
	int end = find(0),number = 0;
	if(in[0]%2) number++;
	for(int i = 1; i < digit ; i ++){
		if(find(i) != end){
			printf("Impossible\n");
			return 0;
		}
		if(in[i] % 2) number++; 
	}
	if(number == 0 || number == 2)
		printf("Possible\n");
	else printf("Impossible\n");
}

猜你喜欢

转载自blog.csdn.net/PK__PK/article/details/82782101
今日推荐