POJ2513-Colored Sticks

题目链接:点击打开链接

Colored Sticks

Time Limit: 5000MS   Memory Limit: 128000K
Total Submissions: 39392   Accepted: 10271

Description

You are given a bunch of wooden sticks. Each endpoint of each stick is colored with some color. Is it possible to align the sticks in a straight line such that the colors of the endpoints that touch are of the same color?

Input

Input is a sequence of lines, each line contains two words, separated by spaces, giving the colors of the endpoints of one stick. A word is a sequence of lowercase letters no longer than 10 characters. There is no more than 250000 sticks.

Output

If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible.

Sample Input

blue red
red violet
cyan blue
blue magenta
magenta cyan

Sample Output

Possible

Hint

Huge input,scanf is recommended.

题目大意:给出n根木棒,木棒两段颜色,只有颜色相同才可以连接,问是否能连成一根木棒。

思路:颜色转化成数字。两个方法:①map(超时)②字典树。 连成一根木棒,并查集+欧拉回路

AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib> 
#include<cstring>
using namespace std;
const int MAXN = 500010;
int father[MAXN];
const int MAX = 26;
int degree[MAXN];//度数 
int color;
//并查集************************ 
int find(int x) { 
	if(father[x] == -1)
		return x;
	return father[x] = find(father[x]);
}

void Union(int x, int y) {
	int fx = find(x);
	int fy = find(y);
	if(fx != fy)
		father[fx] = fy;
}
//字典树**************************** 
typedef struct Trie_Node{ 
	bool isword;//是否是单词结束 
	int id;//编号 
	struct Trie_Node *next[MAX];
	Trie_Node() {//初始化 
		isword = false;
		int id = 0;
		for(int i = 0; i < MAX; i++)
			next[i] = NULL;
	}
}trie;

int insert(trie *root, char *s) {
	trie *p = root;
	int i = 0;
	while(s[i]) {//跑s串 
		if(p->next[s[i]-'a'] == NULL) {//如果该位置 找不到 s[i], 就开一个,指向它 
			trie *temp = new trie();
			p->next[s[i]-'a'] = temp;
		} 
		p = p->next[s[i]-'a'];//继续跑 
		i++;
	}
	if(p->isword)//如果之前有过了,直接返回编号 
		return p->id;
	else {//之前没有,就先标记,然后赋值,返回值。 
		p->isword = true;
		p->id = color++;
		return p->id;
	}
}

void del(trie *root) {//删除 
	for(int i = 0; i < 26; i++) {
		if(root->next[i] != NULL)//这个节点还有26个 
			del(root->next[i]);
	}
	free(root);
} 

int main() {
	char s1[20], s2[20];
	trie *root = new trie();
	color = 0;
	memset(father, -1, sizeof(father));//初始-1  并查集都可以这样写,这道题的颜色编号每处理,这样写更好 
	memset(degree, 0, sizeof(degree));
	while(~scanf("%s%s", s1, s2)) {
		int t1 = insert(root, s1);//插入字典树,返回编号 
		int t2 = insert(root, s2);
		degree[t1]++;//入读++ 
		degree[t2]++;
		Union(t1, t2);
	}
	bool flag = true;
	int tt = find(0);//找到根,每个的祖先都应该是它 
	int cnt = 0;
	for(int i = 0; i < color; i++) {
		if(find(i) != tt) flag = false;
		if(!flag) break;
		if(degree[i]%2 == 1) cnt++;// 度数为奇数只能是0 或者 2 
		if(cnt > 2) flag = false;
	}
	if(cnt == 1) flag =false;
	if(flag) printf("Possible\n");
	else printf("Impossible\n");
	del(root);
}

 推荐博客:神犇kuangbin        浅谈字典树

猜你喜欢

转载自blog.csdn.net/qq_40932661/article/details/81093789