• UVA10129 POJ1386 HDU1116 ZOJ2016 Play on Words【欧拉回路+并查集】


    问题链接:UVA10129 POJ1386 HDU1116 ZOJ2016 Play on Words

    问题简述:先输入测试用例数T,每个测试用例包括整数N和N个单词数,问这些单词首尾字母能否接成一条龙?

    问题分析:这是一个单词接龙问题,一个单词的尾字母和另外一个单词的首字母相同则可以接成龙。其中,每个单词只包含小写字母。单词的首字母和尾字母可以作为图的一个结点,从单词的首字母到尾字母画一条有向边,单词接龙问题就变成一笔画问题,或称为欧拉路径问题。

    欧拉路径问题有两个条件,一是图是联通的;二是所有结点出入度相同,或者只有两个结点出入度差为1。

    程序说明:用并查集来判定图是否是联通的。

    程序提交后,除了POJ1386出现TLE,其他3个在线评判都AC了。在高人指点之下,程序中增加了69行的代码“ios::sync_with_stdio(false);”,就都可以通过了。这是由于C++的输入输出比较慢的原因,通过这行代码,改善了I/O的速度。

    这个语句也可以写为“std::ios::sync_with_stdio(false);”。担心C++输入输出慢,可以使用该语句改善速度。


    AC的C++语言程序如下:

    /* UVA10129 Play on Words */
    
    #include <iostream>
    #include <string>
    #include <cstring>
    
    using namespace std;
    
    const int N = 26;
    
    // 并查集类
    int v[N];
    class UF {
    private:
        int length;
    public:
        UF(int n) {
            length = n;
            for(int i=0; i<=n; i++)
                v[i] = i;
        }
    
        // 压缩
        int Find(int x) {
            if(x == v[x])
                return x;
            else
                return v[x] = Find(v[x]);
        }
    
        bool Union(int x, int y) {
            x = Find(x);
            y = Find(y);
            if(x == y) {
                return false;
            } else {
                v[x] = y;
                return true;
            }
        }
    };
    
    int degreeout[N];
    int degreein[N];
    
    // 出入度检查:return nopathflag
    bool degreeincheck()
    {
        int startcount = 0, endcount = 0;
    
        for(int i=0; i<N; i++)
            if(degreeout[i] != degreein[i]) {
                if((degreeout[i] - degreein[i]) == 1) {
                    if(++startcount > 1)
                        return true;
                } else if((degreeout[i] - degreein[i]) == -1) {
                    if(++endcount > 1)
                        return true;
                } else
                    return true;
            }
        return false;
    }
    
    int main()
    {
        int t, n, src, dest;
    
        ios::sync_with_stdio(false);
    
        cin >> t;
        while(t--) {
            UF uf(N+1);
    
            memset(degreeout, 0, sizeof(degreeout));
            memset(degreein, 0, sizeof(degreein));
    
            // 输入测试用例的数据,构建并查集,统计各个结点的度
            cin >> n;
            string s;
            while(n--) {
                cin >> s;
    
                src = s[0] - 'a';
                dest = s[s.size() - 1] - 'a';
    
                degreeout[src]++;
                degreein[dest]++;
    
                uf.Union(src, dest);
            }
    
            // 判断图的联通性
            bool nopathflag = false;
            int root = -1;
            for(int i=0; i<N; i++) {
                if(degreeout[i] || degreein[i]) {
                    if(root == -1)
                        root = uf.Find(i);
                    else if(uf.Find(i) != root) {
                        nopathflag = true;
                        break;
                    }
                }
            }
    
            // 判定是否存在欧拉路径:出入度检查
            if(!nopathflag)
                nopathflag = degreeincheck();
    
            // 输出结果
            if(nopathflag)
                cout << "The door cannot be opened." << endl;
            else
                cout << "Ordering is possible." << endl;
    
        }
    
        return 0;
    }


  • 相关阅读:
    分治与线段树
    PAT甲级 1006
    PAT甲级 1001
    单源最短路 Dijkstra
    图的邻接矩阵与邻接表
    Huffman树 建树方法代码实现
    小根堆模板类
    二叉搜索树的搜索和插入与删除算法优化
    完全二叉树模板
    二叉树模板及二叉树的无递归遍历
  • 原文地址:https://www.cnblogs.com/tigerisland/p/7564103.html
Copyright © 2020-2023  润新知