zoukankan      html  css  js  c++  java
  • POJ2513——Colored Sticks(Trie树+欧拉回路+并查集)

    Colored Sticks


    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

    题目大意:

        给定一些木条,木条的两头都有颜色,颜色相同的两根木条可以相连,问是否可以连成一条直线。

    解题思路:

        其实就是问是否可以构成欧拉路径。这里给出欧拉路径的定义。

        若图G中存在这样一条路径,使得它恰通过G中每条边一次,则称该路径为欧拉路径。若该路径是一个圈,则称为欧拉(Euler)回路。(即一笔画问题)

        存在欧拉路径的成分必要条件为:一个无向图存在欧拉回路,当且仅当该图只存在0或2个奇数入度数的顶点,且该图是连通图

        1)判断 奇数度数的个数

          很好搞定,建立一个数组存放每个节点的入度,建图结束后遍历即可。

        2)判断是否为连通图

          使用并查集和路径压缩来做。若路径压缩之后每个点都有着相同的父节点(即每个点都有相同的祖先节点)。说明图连通。

        Trie树的应用

        由于该题的Node为字符串,建图的时候会比较困难。使用map映射会超时,所以使用Trie树来进行映射。具体实现请看代码备注。

    Code:

      1 /*************************************************************************
      2     > File Name: poj2513.cpp
      3     > Author: Enumz
      4     > Mail: 369372123@qq.com
      5     > Created Time: 2014年10月26日 星期日 20时16分17秒
      6  ************************************************************************/
      7 
      8 #include<iostream>
      9 #include<cstdio>
     10 #include<cstdlib>
     11 #include<string>
     12 #include<cstring>
     13 #include<list>
     14 #include<queue>
     15 #include<stack>
     16 #include<map>
     17 #include<set>
     18 #include<algorithm>
     19 #include<cmath>
     20 #define MAXN 500001
     21 using namespace std;
     22 class TrieTree_Node
     23 {
     24     public:
     25         bool flag;    //判断是否为一个单词的叶子节点
     26         int id;       //为每一个单词分配一个id,相当于映射关系
     27         TrieTree_Node *next[27];
     28         TrieTree_Node()
     29         {
     30             flag=0;
     31             id=0;
     32             memset(next,0,sizeof(next));
     33         }
     34 }root;
     35 int cnt=0;
     36 int degree[MAXN];   //入度数组
     37 int father[MAXN];
     38 int tree(char *s)
     39 {
     40     TrieTree_Node *p=&root;
     41     int len=strlen(s);
     42     for (int i=0;i<=len-1;i++)
     43     {
     44         int tmp=s[i]-'a';
     45         if (p->next[tmp]==NULL)
     46             p->next[tmp]=new TrieTree_Node;
     47         p=p->next[tmp];
     48     }
     49     if (p->flag)        //如果找到了该字符串,返回其ID
     50         return p->id;
     51     else                //没有找到,就创建这个字符串,并标记叶子节点,分配ID
     52     {
     53         p->flag=1;
     54         p->id=++cnt;
     55         return p->id;
     56     }
     57 }
     58 int find(int a)
     59 {
     60     if (father[a]!=a)
     61         father[a]=find(father[a]);
     62     return father[a];
     63 }
     64 void join(int a,int b)
     65 {
     66     int fx=find(a),fy=find(b);
     67     if (fx!=fy)
     68         father[fx]=fy;
     69 }
     70 void init()
     71 {
     72     for (int i=0;i<MAXN;i++)        //并查集初始化,每一个节点相当于一棵树
     73         father[i]=i;
     74 }
     75 int main()
     76 {
     77     char a[11],b[11];
     78     init();
     79     while (scanf("%s %s",a,b)!=EOF)     //无向图,两个Node的入度都要加
     80     {
     81         int i=tree(a);
     82         int j=tree(b);
     83         degree[i]++;
     84         degree[j]++;
     85         join(i,j);
     86     }
     87     bool ok=1;
     88     int cnt_degree=0;
     89     for (int i=1;i<=cnt;i++)
     90         if (degree[i]%2!=0) cnt_degree++;
     91     if (!(cnt_degree==0||cnt_degree==2))
     92         ok=0;
     93     if (ok)
     94     {
     95         int tmp=find(1);
     96         for (int i=2;i<=cnt;i++)
     97         {
     98             if (tmp!=find(i))
     99                 ok=0;
    100         }
    101     }
    102     if (ok)
    103         cout<<"Possible"<<endl;
    104     else
    105         cout<<"Impossible"<<endl;
    106     return 0;
    107 }

        

  • 相关阅读:
    CentOS 7.3离线安装 JDK
    七:程序是在何种环境下运行的
    六:亲自尝试压缩数据
    五:内存和磁盘的亲密关系
    四:熟练使用有棱有角的内存
    三:计算机进行小数运算时出错的原因
    二:数据是用二进制数表示的
    一:对程序员来说CPU是什么?
    单元测试的艺术-入门篇
    蔡康永的说话之道2-透过说话,懂得把别放在心上
  • 原文地址:https://www.cnblogs.com/Enumz/p/4062872.html
Copyright © 2011-2022 走看看