题目链接:点击打开链接
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
");
else printf("Impossible
");
del(root);
}
推荐博客:神犇kuangbin 浅谈字典树