• 算法笔记_148:有向图欧拉回路求解(Java)


    目录

    1 问题描述

    2 解决方案

     


    1 问题描述

    Description

    A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For example, the following are catenyms: 
    dog.gopher
    
    gopher.rat
    rat.tiger
    aloha.aloha
    arachnid.dog

    A compound catenym is a sequence of three or more words separated by periods such that each adjacent pair of words forms a catenym. For example, 

    aloha.aloha.arachnid.dog.gopher.rat.tiger 

    Given a dictionary of lower case words, you are to find a compound catenym that contains each of the words exactly once.

    Input

    The first line of standard input contains t, the number of test cases. Each test case begins with 3 <= n <= 1000 - the number of words in the dictionary. n distinct dictionary words follow; each word is a string of between 1 and 20 lowercase letters on a line by itself.

    Output

    For each test case, output a line giving the lexicographically least compound catenym that contains each dictionary word exactly once. Output "***" if there is no solution.

    Sample Input

    2
    6
    aloha
    arachnid
    dog
    gopher
    rat
    tiger
    3
    oak
    maple
    elm
    

    Sample Output

    aloha.arachnid.dog.gopher.rat.tiger
    ***
    

    Source


    2 解决方案

    具体代码如下:

     

    package com.liuzhen.practice;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Scanner;
    
    public class Main {
        public static int MAX = 30;   //英文字母共26个
        @SuppressWarnings("unchecked")
        public static ArrayList<edge>[] map = new ArrayList[MAX];
        public static String[] path;
        public static int count;  //统计DFS遍历访问的边数目,即检测图的连通性
        public static int start;
        public static int[] inDegree = new int[MAX];
        public static int[] outDegree = new int[MAX];
        public static ArrayList<String> result = new ArrayList<String>();
        
        class MyComparator implements Comparator<edge> {
    
            public int compare(edge arg0, edge arg1) {
                String A = arg0.word;
                String B = arg1.word;
                int judge = A.compareTo(B);
                if(judge > 0)
                    return 1;
                else if(judge < 0)
                    return -1;
                return 0;
            }
            
        }
        
        static class edge {
            public int a; //单词的第一个字母序号
            public int b; //单词最后一个字母序号
            public String word;  //具体单词
            public boolean used;     //判断单词是否被访问
            
            public edge(int a, int b, String word) {
                this.a = a;
                this.b = b;
                this.word = word;
                used = false;
            }
        }
        
        public void init(int k) {
            start = MAX;
            for(int i = 0;i < MAX;i++) {
                map[i] = new ArrayList<edge>();
                inDegree[i] = 0;
                outDegree[i] = 0;
            }
            path = new String[k];
            for(int i = 0;i < k;i++)
                path[i] = "";
            count = 0;
        }
        
        public boolean judgeDegree() {
            int in = 0, out = 0;
            for(int i = 1;i < map.length;i++) {  //对map[i]中单词进行字典序排序
                if(map[i].size() > 1) 
                    Collections.sort(map[i], new MyComparator());
            }
            
            for(int i = 0;i < inDegree.length;i++) {
                if(inDegree[i] == outDegree[i])
                    continue;
                else if(inDegree[i] - outDegree[i] == 1)
                    in++;
                else if(outDegree[i] - inDegree[i] == 1) {
                    out++;
                    start = i;   //此时,可能存在欧拉路径,必须从入度小于出度的点开始遍历
                } else 
                    return false;
            }
            if(in == out && (in == 0 || in == 1))
                return true;
            return false;
        }
        
        public void dfs(int begin) {
            for(int i = 0;i < map[begin].size();i++) {
                edge temp = map[begin].get(i);
                if(temp.used == false) {
                    temp.used = true;
                    path[count++] = temp.word;
                    dfs(temp.b);
                }
            }
        }
        
        public static void main(String[] args) {
            Main test = new Main();
            Scanner in = new Scanner(System.in);
            int t = in.nextInt();
            while(t > 0) {
                t--;
                int k = in.nextInt();
                test.init(k);
                for(int i = 0;i < k;i++) {
                    String A = in.next();
                    int a = A.charAt(0) - 'a';
                    int b = A.charAt(A.length() - 1) - 'a';
                    start = Math.min(start, Math.min(a, b));
                    map[a].add(new edge(a, b, A));
                    outDegree[a]++;
                    inDegree[b]++;
                }
                StringBuilder temp = new StringBuilder("");
                if(test.judgeDegree()) {  //满足欧拉回路或者欧拉路径对顶点度的要求
                    test.dfs(start);
                    if(count == k) {  //图连通
                        for(int i = 0;i < k;i++) {
                            temp.append(path[i]);
                            if(i != k - 1)
                                temp.append(".");
                        }
                    } else {
                        temp.append("***");
                    }
                } else {
                    temp.append("***");
                }
                result.add(temp.toString());
            }
            for(int i = 0;i < result.size();i++)
                System.out.println(result.get(i));
        }
    }

    运行结果:

    2
    6
    aloha
    arachnid
    dog
    gopher
    rat
    tiger
    3
    oak
    maple
    elm
    aloha.arachnid.dog.gopher.rat.tiger
    ***

     

     

     

     

    参考资料:

       1. 欧拉回路

  • 相关阅读:
    java语法基础
    向linux内核增加一个系统调用-1
    dp-矩阵连乘
    struct和typedef struct
    Ubuntu安装Chrome及hosts修改
    c++primer-p100.用迭代器进行二分法搜索
    c++primer-p101.ex3.24
    c++ vector用法和迭代器
    Bytes和bits的区别(字节和位的区别)
    基于R语言的数据分析和挖掘方法总结——中位数检验
  • 原文地址:https://www.cnblogs.com/liuzhen1995/p/6768268.html
Copyright © 2020-2023  润新知