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 }

 

    

posted @ 2014-10-30 15:41  Enumz  阅读(235)  评论(0编辑  收藏  举报