zoukankan      html  css  js  c++  java
  • POJ 2513 (Trie树+欧拉通路+并查集判断连通)

    题目:http://poj.org/problem?id=2513

    两个教训:

      一、输入输出用scanf、printf(好像自己已经强调很多遍了= =……)

        eg:用cin 1000MS 用scanf 400MS…………

      二、不要把string作为函数值传递参数(推广到整个STL,STL加了很多没用的功能会导致效率变低) 

         eg:此题Trie中的参数用string 4485MS 用char * 985MS…………

    /*
    题目大意:每个木棒头尾都有两种颜色,木棒末端颜色相同的可以连接成一条直线,问能否将所有木棒连接起来组成一条直线。
    题目求解:传换成图的问题就是求解能否一笔画成(欧拉通路)
    代码技巧:用数组字典树和链表字典树都可以,动态链表空间少好写,静态数组速度快,看情况吧。
    */
    
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <iomanip>
    #include <climits>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <algorithm>
    #include <string>
    #include <cstring>
    
    using namespace std;
    
    #define N 500005
    
    struct set
    {
        int parent;  //记录父节点
        int rank;    //记录集合的节点数
    }elem[N];
    
    int MAX;
    
    void init()
    {
        int i;
        for(i=0;i<=N;i++)
        {
            elem[i].parent=i;
            elem[i].rank=1;
        }
    }
    
    int Find(int x)
    {
        int root,temp;
        temp=x;
        while(x!=elem[x].parent)    //寻找根节点
            x=elem[x].parent;
        root=x;
        x=temp;
        while (x!=elem[x].parent)   //压缩路径,全部赋值为根节点的值
        {
            temp=elem[x].parent;
            elem[x].parent=root;
            x=temp;
        }
        return root;
    }
    
    void Union(int a,int b)   //合并两个集合
    {
        int x,y;
        x=Find(a);
        y=Find(b);
        if(elem[x].rank>=elem[y].rank)
        {
            elem[y].parent=elem[x].parent;
            elem[x].rank+=elem[y].rank;
            if(MAX<elem[x].rank)
                MAX=elem[x].rank;
        }
        else
        {
            elem[x].parent=elem[y].parent;
            elem[y].rank+=elem[x].rank;
            if(MAX<elem[y].rank)
                MAX=elem[y].rank;
        }
    }
    //Trie树模板   by AbandonZHANG
    
    
    int words_num;
    int degree[500005];
    
    struct Trie_node
    {
        //int Ch_Count;   //统计单词个数,如果为0表示没有该串。
        int hash;       //单词hash后的标识数
        Trie_node *next[26];//指向各个子树的指针,下标0-25代表26字符,如果是数字改成10就行了
        Trie_node()
        {
            //Ch_Count=0;
            hash=-1;
            memset(next,NULL,sizeof(next));
        }
    };
    
    class Trie
    {
    public:
        Trie();
        int insert(char *word);                //插入新单词
    private:
        Trie_node* root;
    };
    
    Trie::Trie()
    {
        root = new Trie_node();
    }
    
    int Trie::insert(char *word)               //边插入边查找
    {
        Trie_node *p = root;
        int len=strlen(word);
        if(len==0) return -1;
        for (int i=0;i<len;i++)
        {
            if(p->next[word[i]-'a'] == NULL)      //如果不存在的话,我们就建立一个新的节点
            {
                Trie_node *tmp = new Trie_node();
                p->next[word[i]-'a'] = tmp;
                p = p->next[word[i]-'a'];         //每插入一步,相当于有一个新串经过,指针要向下移动
            }
            else                                //如果这个节点之前就已经存在呃,我们只需要把统计次数加上1
                p=p->next[word[i]-'a'];
            //p->Ch_Count++;                      //这里是求所有前缀出现的次数,如果只求整个单词出现次数则用后一个
        }
        //p->Ch_Count++;                              //求整个单词的出现次数
    
        if (p->hash<0)
            p->hash=words_num++;
    
        return p->hash;
    }
    
    Trie t;
    
    
    int main()
    {
        //freopen("test.in","r",stdin);
    
        init();
        char a1[15],a2[15];
        words_num=0;
        while(scanf("%s%s",a1,a2)!=EOF)
        {
            int x,y;
            x=t.insert(a1);
            degree[x]++;
            y=t.insert(a2);
            degree[y]++;
            Union(x,y);
        }
        int sum=0;
        for (int i=0;i<words_num;i++)
        {
            if (degree[i]%2==1)
                sum++;
            if (sum>2)
            {
                printf("Impossible\n");
                return 0;
            }
        }
    
        for (int i=0;i<words_num;i++)
            if (Find(i)!=Find(0))
            {
                printf("Impossible\n");
                return 0;
            }
        printf("Possible\n");
        return 0;
    }
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    UVA 10827 Maximum sum on a torus 最大矩阵和
    UVA 11100 The Trip, 2007 水题一枚
    编程之美2015测试赛 题目1 : 同构
    UVA 10801 Lift Hopping Floyd
    UVA 11389 The Bus Driver Problem 贪心水题
    UVA 11039 Building designing 贪心
    UVA 11636 Hello World! 水题
    poj 3070 Fibonacci 矩阵快速幂
    hdu 1757 A Simple Math Problem 矩阵快速幂
    了解常见的 Azure 灾难
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/2626644.html
Copyright © 2011-2022 走看看