zoukankan      html  css  js  c++  java
  • UVA 10129 Play on Words (欧拉通路)

    本文链接:http://www.cnblogs.com/Ash-ly/p/5398627.html

    题意:

      输入N(N <= 100000)个单词,是否可以把所有这些单词排成一个序列,使得每个单词的第一个字母和上一个单词的最后一个字母相同(例如:acm,malform,mouse)。每个单词最多包含 1000 个小写字母。输入中可以有重复的单词。

    思路:

      把一个字母的两端开成节点,单词看成有向边,若问题有借,当且仅当图中存在欧拉通路。所有只需要判断由单词而构建的图是否存在欧拉通路,由于是有向边,所以利用有向图欧拉通路的判定就可以了。

    判定条件

    (1):底图是连通图

    (2):可以有两个奇点,其中一个出度比入度大 1,另外一个入度比出度大1.

    对于条件1,在这里用并查集判断了,条件2统计每个点的出度,入度,加以判断就行了.

    代码:

    #include <stdio.h>  
    #include <string.h>  
    #include <iostream>  
    #include <math.h>
    #include <queue>
    #include <stack>
    #include <algorithm>
    using namespace std;  
    
    const int maxV = 29;
    int m;
    int pre[maxV + 7];
    int outdegree[maxV + 7];
    int indegree[maxV + 7];
    
    int Find(int x){return x == pre[x] ? x : pre[x] = Find(pre[x]); }//并查集的查找
    void initPre(){ for(int i = 0; i <= maxV; i++) pre[i] = i; }//初始化并查集的数组
    
    int mix(int x, int y)//并查集的合并
    {
        int fx = Find(x), fy = Find(y);    
        if(fx != fy) pre[fx] = fy;    
    }
    
    bool isConnct()//判断图是否连通,即所有的点都在一个集合里面
    {
        int cnt = 0;
        for(int i = 1; i <= maxV; i++)if( (outdegree[i] != 0 || indegree[i] != 0) && pre[i] == i) cnt++;
        if(cnt == 1)return true;
        return false;
    }
    
    bool isEulur()//是否存在欧拉通路
    {
        int cnt = 0;
        int flag = 0;
        for(int i = 1; i <= 26; i++)
            if((outdegree[i] != 0 || indegree[i] != 0) && (indegree[i] != outdegree[i]))//判断奇点,方法不唯一。
            {
                cnt++;
                flag += (indegree[i] - outdegree[i]);
                if(flag > 1 || flag < -1) return false;
            } 
        if(cnt == 0 || cnt == 2 && flag == 0) return true;
        return false;
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            scanf("%d", &m);
            initPre();
            memset(indegree, 0, sizeof(indegree));
            memset(outdegree, 0, sizeof(outdegree));
            for(int i = 1; i <= m; i++)
            {
                char word[1000 + 7];
                scanf("%s", word);
                int u = word[0] - 'a' + 1;
                int len = strlen(word);
                int v = word[len - 1] - 'a' + 1;
                mix(u, v);
                ++outdegree[u];
                ++indegree[v];
            }
            if(isEulur() && isConnct())    printf("Ordering is possible.
    ");
            else                        printf("The door cannot be opened.
    ");
        }
        return 0;
    }
  • 相关阅读:
    151. 翻转字符串里的单词(trim函数与split函数的使用)
    Java splt方法,按照空格分割字符串成为字符串数组(转载)
    137. 只出现一次的数字 II(没完全按要求做)
    129. 求根到叶子节点数字之和(递归
    125. 验证回文串(replaceAll()与toLowerCase())
    美团上海Java实习(已offer)面经(还没写完,转载)
    二叉树中序遍历
    优先队列/最大堆
    防御式编程
    JWT
  • 原文地址:https://www.cnblogs.com/Ash-ly/p/5398627.html
Copyright © 2011-2022 走看看