zoukankan      html  css  js  c++  java
  • NYOJ236 彩色棒 字典树 + 并查集 + 欧拉路

     

    彩色棒

    时间限制: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 }
    
    
    功不成,身已退
  • 相关阅读:
    Linux删除tunnel的方法
    rpm 强制更新安装
    普通用户使用kubectl
    网络通信过程中mac地址和ip地址的必要性
    Quartz.net开源作业调度框架使用详解
    C# 开源组件--Word操作组件DocX
    用c#创建支持多语言的WinForm应用程序
    使用JavaScript获取日期加随机数生成单号
    C# winform treeView checkbox全选反选
    DevExpress控件的GridControl控件小结
  • 原文地址:https://www.cnblogs.com/dongsheng/p/2630957.html
Copyright © 2011-2022 走看看