• POJ 2513 Colored Sticks(字典树 + 并查集 + 欧拉回路)


    Colored Sticks

    Time Limit: 5000MS

     

    Memory Limit: 128000K

    Total Submissions: 23116

     

    Accepted: 6095

    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

    The UofA Local 2000.10.14

     解题报告:题意就是给我们n个带颜色的木棍,看是否能排成一排(相接的颜色必须是一样的),

    解题思路是看的别人的:判断无向图中是否存在欧拉通路,判断条件是:

    1、有且只有两个度为奇数的节点

    2、图是连通的

    由于节点是字符串,因此我们可以利用字典树将其转换成一个颜色序号。这样,统计每种颜色的出现次数就可以了。判断图是否连通,可以利用并查集:若最后所有节点在同一个集合,则图是连通的。

    代码如下:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    const int MAX = 500010;
    using namespace std;
    int father[MAX];//father[x]表示x的父节点 
    int rank[MAX];//rank[x]表示x的秩
    int degree[MAX];//degree记录节点的度 
    int num = 0;//记录字典树有效节点个数 
    struct Trie//字典树节点的类型
    {
        int flag;
        struct Trie *next[26];
    };
    struct Trie *Root;//字典树的根节点
    struct Trie *NewSet()//创建新节点的函数
    {
        int i;
        struct Trie *p;
        p = (struct Trie *)malloc(sizeof(struct Trie));//开辟新节点
        for (i = 0; i < 26; ++i)//初始化
        {
            p->next[i] = NULL;
        }
        p->flag = 0;
        return p;
    }
    int Insert(char *s)//以Root为根插入字符串函数
    {
        int i, len;
        struct Trie *p;
        p = Root;
        len = strlen(s);
        for (i = 0; i < len; ++i)
        {
            //节点不存在时创建新的节点
            if (p->next[s[i] - 'a'] == NULL)
            {
                p->next[s[i]- 'a'] = NewSet();
            }
            p = p->next[s[i] -'a'];
        }
        if (p->flag == 0)
        {
            p->flag = ++num;//得到并返回颜色节点序号 
        }
        return p->flag;
    }
    void MakeSet()//初始化函数
    {
        int i;
        for (i = 0; i < MAX; ++i)
        {
            father[i] = i;
            rank[i] = 0;
            degree[i] = 0;
        }
    }
    int Find(int i)
    {
        if (father[i] != i)//路径压缩
        {
            father[i] = Find(father[i]);
        }
        return father[i];
    }
    void Merge(int x, int y)//合并函数
    {
        int i, j;
        i = Find(x);
        j = Find(y);
        if (i != j)
        {
            if (rank[i] > rank[j])
            {
                father[j] = i;
            }
            else
            {
                if (rank[i] == rank[j])
                {
                    rank[j] ++;
                }
                father[i] = j;
            }
        }
    }
    int main()
    {
        int i, sum, x, y;
        char str1[26], str2[26];
        MakeSet();
        Root = NewSet();
        while (scanf("%s%s", str1, str2) != EOF)
        {
            x = Insert(str1);
            y = Insert(str2);
            degree[x] ++;//度数加一
            degree[y] ++;
            Merge(x, y);
        }
        sum = 0;//记录度数为奇数的个数
        //求度数为奇数的点的个数
        for (i = 0; i < num; ++i)
        {
            if (degree[i] % 2)
            {
                sum ++;
            }
        }
        int Flag = 1;//假设可以连在一块
        //若度大于2则肯定不可能
        if (sum > 2)
        {
            Flag = 0;
        }
        else//判断图是否连通
        {
            for (i = 2; i < num; ++i)//是否所有的点在一个集合中
            {
                if (Find(i) != Find(1))//若不在一个集合中
                {
                    Flag = 0;
                }
            }
        }
        if (Flag)
        {
            printf("Possible\n");
        }
        else
        {
            printf("Impossible\n");
        }
        return 0;
    }

     

  • 相关阅读:
    hdu2089 不要62 (数位dp)
    LightOJ 1140
    在n到m中 有多少个1 (数位dp)
    Frequent Subsets Problem 状态压缩 判断出现的次数
    LightOj 1215
    LightOJ 1197
    Spring 知识点提炼
    设计模式—访问者模式
    设计模式—模板模式
    设计模式—策略模式
  • 原文地址:https://www.cnblogs.com/lidaojian/p/2444747.html
Copyright © 2020-2023  润新知