彩色棒
时间限制:
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
1 /* 功能Function Description: 字典树 + 并查集 + 欧拉路 2 开发环境Environment: DEV C++ 4.9.9.1 3 技术特点Technique: 4 版本Version: 5 作者Author: 可笑痴狂 6 日期Date: 20120809 7 备注Notes: 8 大致题意: 9 给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线, 10 要求不同木棒相接的一边必须是相同颜色的。 11 解题思路: 12 可以用图论中欧拉路的知识来解这道题,首先可以把木棒两端看成节点,把木棒看成边,这样相同的颜色就是同一个节点 13 问题便转化为: 14 给定一个图,是否存在“一笔画”经过涂中每一点,以及经过每一边一次。 15 这样就是求图中是否存在欧拉路Euler-Path。 16 */ 17 #include<stdio.h> 18 #include<string.h> 19 #include<malloc.h> 20 typedef struct node 21 { 22 int order; //存储该颜色在对应数组中的编号 23 struct node *next[26]; 24 }node; 25 26 int father[500005]; //并查集中记录父亲节点 27 int degree[500005]; //记录每个颜色出现的次数,用于欧拉路的判断 28 //node memory[1000000]; 29 int t,k; //t为记录标号增加的数组指针,k为静态内存分配时的数组指针 30 31 int search(char *s,node *T) //返回s所表示的颜色在数组中的编号 32 { 33 int len,i,j,id,flag=0; 34 node *p,*q; 35 len=strlen(s); 36 p=T; 37 for(i=0;i<len;++i) 38 { 39 id=s[i]-'a'; 40 if(p->next[id]==NULL) 41 { 42 flag=1; 43 // q=&memory[k++]; 44 q=(node *)malloc(sizeof(node)); 45 for(j=0;j<26;++j) 46 q->next[j]=NULL; 47 p->next[id]=q; 48 } 49 p=p->next[id]; 50 } 51 if(flag) //肯定是新出现的颜色---因为有新开辟的节点 52 { 53 p->order=t; //t存储该颜色在数组中对应的编号 54 degree[t++]++; //该颜色的度增加一 55 return p->order; 56 } 57 else 58 { 59 if(p->order==0) //也是新颜色----因为没有颜色在此标记 60 { 61 p->order=t; //t存储该颜色在数组中对应的编号 62 degree[t++]++; //该颜色的度增加一 63 return p->order; 64 } 65 degree[p->order]++; //出现过的颜色,对应的度增加一 66 return p->order; 67 } 68 } 69 70 int find_father(int i) 71 { 72 if(father[i]==-1) 73 return i; 74 else 75 return find_father(father[i]); 76 } 77 78 void merge(int num1,int num2) 79 { 80 num1=find_father(num1); 81 num2=find_father(num2); 82 if(num1!=num2) 83 { 84 if(father[num1]<father[num2]) //father[num1]的绝对值大 85 father[num2]=num1; 86 else 87 father[num1]=num2; 88 } 89 } 90 int main() 91 { 92 int m,n,i,num1,num2,flag; 93 char s1[20],s2[20]; 94 node *T; 95 scanf("%d",&m); 96 while(m--) 97 { 98 // k=0; 99 t=1; //从1号开始算起 100 flag=0; 101 memset(father,-1,sizeof(father)); 102 memset(degree,0,sizeof(degree)); 103 // T=&memory[k++]; 104 T=(node *)malloc(sizeof(node)); 105 T->order=0; 106 for(i=0;i<26;++i) 107 T->next[i]=NULL; 108 scanf("%d",&n); 109 if(n==0) //注意题中测试数据当有0种颜色时输出 Possible 110 { 111 printf("Possible\n"); 112 continue; 113 } 114 while(n--) 115 { 116 scanf("%s%s",s1,s2); 117 num1=search(s1,T); 118 num2=search(s2,T); 119 merge(num1,num2); 120 } 121 for(i=1;i<t;++i) //共有t-1种颜色 122 if(father[i]==-1) 123 ++flag; 124 if(flag>1) //说明不连通 125 printf("Impossible\n"); 126 else 127 { 128 flag=0; 129 for(i=1;i<t;++i) 130 if(degree[i]&1) //统计奇数度结点出现的次数 131 ++flag; 132 if(flag==2||flag==0) //无向图G具有一条欧拉路,当且仅当G是连通的,且有零个或两个奇数度结点 133 printf("Possible\n"); 134 else 135 printf("Impossible\n"); 136 } 137 } 138 return 0; 139 }