zoukankan      html  css  js  c++  java
  • POJ 2513 -- Colored Sticks

    Colored Sticks
    Time Limit: 5000MS   Memory Limit: 128000K
    Total Submissions: 38355   Accepted: 10044

    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

    Hint

    Huge input,scanf is recommended.

    Source

     

    题意:

    给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相接的一边必须是相同颜色的。

    解题思路:

      将每一根火柴棍,看成一条边,相同的颜色为同一个点,这样我们可以把原问题转化为,是否可以画一条线,经过所有边一次且仅一次。这就是欧拉图,问是否存在欧拉通路(或者欧拉回路也可以)。

      欧拉通路也叫半欧拉图,欧拉回路也叫欧拉图。

      无向图G是半欧拉图 当且仅当  1.G是连通的  2.恰有两个奇度定点

      无向图G是欧拉图 当且仅当  1.G是连通的  2.没有奇度定点

      ps:或许与人会注意到,每次插入的是一条边,每条边上有两个点,那么是否可以这样想:如果有两条边有颜色相同的点,那么就把这两个点粘起来,形成一条新边,这样一直插入所有边,如果木棍能够连接成一条直线,那么最后应该只剩下两个端点,如果大于两个端点,就不能连成一条直线。因为每次输入的是一条边,所以输入的两个点一定是连通的,将它与另一个边相接,新生成的木棍一定也是连通的,所以这种不像是判断欧拉图那样一个点一个点的输入,是否可以不判断连通性?答案是不可以,因为木棍可能两端点同色,这样,木棍在我们的模拟中,就会退化成一个点,所以这个问题又退化成了单点输入的欧拉图问题。

      所以我们首先判断奇度定点的个数。将颜色string与出现次数int联系起来

      如果使用map的话会超时,虽然STL的map是基于hash的基础上,但并不高效

      这里使用字典树为每个字符串一个编号。

      关于字典树=》浅谈Trie树(字典树)

      判断是否联通肯定就是用并查集了。使用并查集时必须压缩路径,前几次搜索某个结点k的祖先时,在不断通过父亲结点寻找祖先结点时,顺便把从k到最终祖先结点S中经过的所有结点的祖先都指向S,那么以后的搜索就能把时间降低到O(1)

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 const int large = 250000*2;//最多有250000*2个结点
     6 int color=0;//记录当前颜色的编号
     7 int Count[large+1] = {0};//第id个结点出现的次数
     8 int ancestor[large+1];//第id个结点的祖先
     9 
    10 class HashTable{
    11 public:
    12     int id;
    13     HashTable *next[27];//存储子树的颜色
    14     HashTable()//初始化
    15     {
    16         id = 0;
    17         memset(next,0,sizeof(next));
    18     }
    19 }root;//根节点root
    20 
    21 int hash(char *a)
    22 {
    23     HashTable *temp = &root;//从根节点开始查找
    24     int i=0;
    25     while(a[i] != '')
    26     {
    27         if(!temp->next[a[i]-'a'])//索引不存在
    28             temp->next[a[i]-'a'] = new HashTable;//创建索引
    29         temp = temp->next[a[i]-'a'];
    30         i++;
    31     }
    32     if(temp->id)//颜色单词已存在
    33         return temp->id;//返回其编号
    34     else{
    35         temp->id = ++color;
    36         return temp->id;
    37     }
    38 }
    39 
    40 int find(int i)
    41 {
    42     if(ancestor[i] != i)
    43         ancestor[i]=find(ancestor[i]);//路径压缩
    44     return ancestor[i];
    45 }
    46 
    47 void union_anc(int i,int j)
    48 {
    49     int pi = find(i);
    50     int pj = find(j);
    51     ancestor[pj] = pi;//使i的祖先作为j的祖先
    52     return;
    53 }
    54 
    55 int main()
    56 {
    57     for(int i=0;i<=large;i++)
    58     {
    59         ancestor[i] = i;//初始化每个颜色id的祖先为自己
    60     }
    61     char a[20],b[20];
    62     while(cin>>a>>b)
    63     {
    64         int i = hash(a);//得到颜色编号
    65         int j = hash(b);
    66         ///计数增加
    67         Count[i]++;
    68         Count[j]++;
    69 
    70         ///将i和j的祖先合并
    71         union_anc(i,j);
    72     }
    73     int s = find(1);//若图为联通图,则s为所有结点的共同祖先
    74                     //若图为非连通图,s为所有祖先中的其中一个祖先
    75     int num = 0;//度数为奇数的节点个数
    76     for(int i=1;i<=color;i++)
    77     {
    78         if(Count[i]%2)//度为奇数
    79             num++;
    80         if(num>=3)
    81         {
    82             cout<<"Impossible"<<endl;
    83             return 0;
    84         }
    85         if(find(i)!=s)
    86         {
    87             cout<<"Impossible"<<endl;
    88             return 0;
    89         }
    90     }
    91     if(num == 1)
    92         cout<<"Impossible"<<endl;
    93     else
    94         cout<<"Possible"<<endl;
    95 
    96     return 0;
    97 }

  • 相关阅读:
    iOS button总结
    蓝鸥 UI 考试 绝密
    iOS UI 21 消息通知
    iOS UI 21 单例中的线程
    iOS UI 21 线程
    iOS UI 21 动画
    iOS UI 20 音乐播放器
    深入Objective-C的动态特性
    符合iOS系统兼容性需求的方法
    IOS用NSLog做 debug调试
  • 原文地址:https://www.cnblogs.com/yxh-amysear/p/8445509.html
Copyright © 2011-2022 走看看