zoukankan      html  css  js  c++  java
  • POJ 2337 Catenyms(有向欧拉图:输出欧拉路径)

    题目链接>>>>>>

    题目大意:

    给出一些字符串,问能否将这些字符串  按照 词语接龙,首尾相接  的规则 使得每个字符串出现一次

    如果可以 按字典序输出这个字符串序列

    #include <iostream>  
    #include <cstdio> 
    #include <string>
    #include <cstring>  
    #include <vector>  
    #include <algorithm>  
    #define M 1050  
    using namespace std;
    int n, top;
    struct edge {
        int to, vis, id;           //to代表边的终点,id代表边的编号
    };
    vector<edge>w[M];
    string str[M];                //原来还可以这样定义字符串数组
    int ans[M];
    int fa[29];
    
    int find(int x)
    {
        return x == fa[x] ? x : fa[x] = find(fa[x]);
    }
    
    void fleury(int loc)
    {
        for (int i = 0; i<w[loc].size(); i++)
            if (!w[loc][i].vis)
            {
                w[loc][i].vis = 1;
                fleury(w[loc][i].to);
                ans[top++] = w[loc][i].id;
            }
        return;
    }
    
    int main()
    {
        int indegree[28], outdegree[28];
        int T;
        scanf("%d", &T);
        while (T--)
        {
            top = 0;
            for (int i = 0; i<26; i++)
            {
                w[i].clear();
                outdegree[i] = indegree[i] = 0;
                fa[i] = i;
            }
            scanf("%d", &n);
            int a, b;
            for (int i = 0; i<n; i++)
                cin >> str[i];
            sort(str, str + n);             //根据字典序排序  
            edge edg;
            int start;
            for (int i = 0; i<n; i++)
            {
                a = str[i][0] - 'a';
                b = str[i][str[i].size() - 1] - 'a';
                indegree[a]++;
                outdegree[b]++;
                fa[find(a)] = find(b);     
                edg.to = b; edg.vis = 0; edg.id = i;
                w[a].push_back(edg);
                if (i == 0)              //重要  起点必须为初始化为第一条边的出节点(字典序最小,且满足 欧拉回路 的的要求)  
                    start = a;
            }
    
            int ss = 0, num = 0, start_num = 0, end_num = 0;
            for (int i = 0; i<26; i++)
            {
                if ((indegree[i] || outdegree[i]) && find(i) == i)          //find(i)==i是用来判断整个图是否连通的,因为图存在欧拉通路的条件之一就是必须是连通图
                    ss++;                                                   //结合下面的ss==1,来理解,因为如果整个图是连通的,ss就只会在当i为根节点的时候+1
                if (indegree[i] != outdegree[i])
                {
                    if (outdegree[i] - indegree[i] == -1)
                        start = i, start_num++;                         //这里和上面的初始化start的步骤不懂,做题的时候就是卡在了选取第一个出节点的步骤
                    else if (outdegree[i] - indegree[i] == 1)
                        end_num++;
                    num++;
                }
            }
            if ((num == 0 || (num == 2 && start_num == 1 && end_num == 1)) && ss == 1)           //存在欧拉通路的条件
            {
                fleury(start);                 //我对start的选取不是很理解
                for (int i = top - 1; i >= 0; i--)             //要使输出的单词按字典序输出
                {
                    if (i == 0)
                        cout << str[ans[i]] << endl;
                    else
                        cout << str[ans[i]] << ".";
                }
            }
            else
                cout << "***" << endl;
        }
        return 0;
    }

    2018-04-07


    作者:is_ok
    出处:http://www.cnblogs.com/00isok/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    初识HTML5
    java_类的有参方法
    示例:人机猜拳(请各位大佬看下)
    java-类和对象(笔记)
    Redis设计与实现——多机数据库的实现
    Redis设计与实现——独立功能的实现
    mina
    GUAVA-cache实现
    GUAVA-ListenableFuture实现回调
    Netty多协议开发
  • 原文地址:https://www.cnblogs.com/00isok/p/8734550.html
Copyright © 2011-2022 走看看