彩色棒

时间限制: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 }

 

 


posted on 2012-08-09 21:52  可笑痴狂  阅读(344)  评论(0编辑  收藏  举报