• POJ 2513 字典树+并查集+欧拉路径


    Description:

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

    解题思路:

    可以用图论中欧拉路的知识来解这道题,首先可以把木棒两端看成节点,把木棒看成边,这样相同的颜色就是同一个节点

    问题便转化为:

    给定一个图,是否存在“一笔画”经过涂中每一点,以及经过每一边一次。

    这样就是求图中是否存在欧拉路Euler-Path。(我才知道这个就是欧拉路径。。。T_T)

    由图论知识可以知道,无向图存在欧拉路的充要条件为:

    ①     图是连通的;  // 用并查集判断就好啦。

    ②     所有节点的度为偶数,或者有且只有两个度为奇数的节点。

    附代码(虽然有点小疑问):

    #include<stdio.h>
    #include<string.h>
    #include<iostream>
    #include<string>
    #define maxn 500000 + 100
    using namespace std;

    int fa[maxn];
    int du[maxn];
    int cnt;

    void init()
    {
        int i;
        for (i=0; i<maxn; ++i)
        {
            fa[i] = i;
        }
        cnt = 0;
    }

    int find(int v)
    {
        if (fa[v] == v) return v;
        return fa[v] = find(fa[v]);
    }

    void unin(int x, int y)
    {
        int fx = find(x);
        int fy = find(y);
        if (fx != fy)
          fa[fx] = fy;
    }

    struct trie
    {
        trie *next[26];
        int key;
        bool isleaf;
        trie()
        {
            for (int i=0; i<26; ++i)
            {
                next[i] = NULL;
            }
            key = 0;
            isleaf = false;
        }
    }Root, Node;

    int creatTree(char word[])
    {
        trie *p = &Root;
        char *str = word;
        while(*str)
        {
           if (p->next[*str-'a'] == NULL)
            p->next[*str-'a'] = new trie;
           p = p->next[*str-'a'];
           str++;
        }
        if (p->isleaf)
            return p->key;
        else
        {
            p->isleaf = true;
            p->key = cnt++;
            return p->key;
        }
    }

    int main()
    {
        char str1[20], str2[20];
        init();
        while(~scanf("%s%s", str1, str2))
        {
            int a, b;
            a = creatTree(str1);
            b = creatTree(str2);
            du[a]++;   // T_T 还是布吉岛为什么。如果这两种颜色已经属于一个集合了。为什么还要度数++呢。所以。额。
            du[b]++;
            if (find(a) != find(b))
            {
    //            du[a]++;
    //            du[b]++;
                unin(a, b);
            }
        }
        int temp = 0;
        for (int i=0; i<cnt; ++i)
        {
            if (du[i] % 2)
                temp++;
        }
        if (temp != 0 && temp != 2)
        {
            printf("Impossible ");
            return 0;
        }
        int ttemp = find(0);
        for (int i=1; i<cnt; ++i)
        {
            if (find(i) != ttemp)
            {
                printf("Impossible ");
                return 0;
            }
        }
        printf("Possible ");
        return 0;
    }

  • 相关阅读:
    WDM驱动加载方式理解
    应用程序与设备对象交换数据的三种方法
    IRP完成例程返回值理解
    关于IoCallDriver使用的疑惑
    Ring0打开其他设备对象三种方式整理
    DPC和ISR的理解
    Windows驱动开发技术详解HelloWDM例子win7下无法安装
    wdk中ramdisk代码解读
    内核编程键盘过滤几种方法思路整理
    IOAPIC重定位中断处理函数思路整理
  • 原文地址:https://www.cnblogs.com/icode-girl/p/4572723.html
Copyright © 2020-2023  润新知