彩色棒
时间限制:
1000 ms | 内存限制:
128000 KB
难度:
5
-
描述
-
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?
-
输入
- the frist line have a number k(0<k<=10),that is the number of case. each case contais a number m,then have m line, 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 13 characters. There is no more than 250000 sticks. 输出
- If the sticks can be aligned in the desired way, output a single line saying Possible, otherwise output Impossible. 样例输入
-
1 5 blue red red violet cyan blue blue magenta magenta cyan
样例输出
-
Possible
思路:
欧拉通路, 判断是否成线, 加并查集, 字典树优化。
#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct Node { int order; Node *next[26]; }node; int cnt, father[250001], degree[250001]; node *newnode() //新建节点 { node *p = (node *)malloc(sizeof(node)); for(int i = 0; i < 26; i++) //初始化节点 { p->next[i] = NULL; } p->order = 0; return p; } int insert(node *root, char str[]) //将颜色插入字典树, 并返回颜色的编号 { int len, flag = 0, i, pos; node *p = root; len = strlen(str); for(i = 0; i < len; i++) { pos = str[i] - 'a'; if(p->next[pos] == NULL) { flag = 1; p->next[pos] = newnode(); } p = p->next[pos]; } if(flag) //若有新建节点, 则一定是新颜色, 记录编号, 并更新度数数组 { p->order = cnt; degree[cnt++]++; } else { if(p->order == 0) //若没有新建节点, 且p->order编号, 也是新颜色 { p->order = cnt; degree[cnt++]++; } else { degree[p->order]++; } } return p->order; //返回节点编号 } int findfather(int x) //寻找根节点 { if(father[x] == -1) { return x; } else { return findfather(father[x]); } } int merge(int a, int b) //将两个点合并到一个集合(并查集) { a = findfather(a); b = findfather(b); if(a != b) { father[a]=b; } return 0; } int main() { char str1[14], str2[14]; int count, t1, t2, i, n, t; node *root; scanf("%d", &t); while(t--) { root = newnode(); memset(father, -1, sizeof(father)); memset(degree, 0, sizeof(degree)); scanf("%d", &n); if(n == 0) //若为空图直接返回Possible { printf("Possible\n"); continue; } cnt = 1; //多组数据,别忘初始化 for(i = 0; i < n; i++) { scanf("%s%s", str1, str2); t1 = insert(root, str1); //将颜色节点重新编号并归入并查集 t2 = insert(root, str2); merge(t1, t2); } count = 0; //重新计数 for(i = 1; i < cnt; i++) { if(father[i] == -1) { count++; } } if(count > 1) //若有多个根节点则有多副图 ,无法连成一条线(成环时count有可能为0) { printf("Impossible\n"); continue; } count = 0; for(i = 1; i < cnt; i++) //判断欧拉通路 { if(degree[i]%2 == 1) { count++; } } if(count == 2 || count == 0) //若偶度节点只有2个(线)或没有(环),成立 { printf("Possible\n"); continue; } else //否则不成立 { printf("Impossible\n"); continue; } } return 0; }