首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >欧拉电路算法

欧拉电路算法
EN

Code Review用户
提问于 2018-03-03 05:01:58
回答 1查看 914关注 0票数 0

这种方法从有向图中画出欧拉电路。该图形由表示传出边的Deques数组表示。如果有更有效的数据类型,就不必是Deques;据我所知,Deque是堆栈最有效的实现,但我可能错了。

我试过用ArrayDeques代替LinkedLists,但没什么区别。

我尝试保留一个数组edgeCount,而不是使用edges[currentVertexNumber].size() > 0检查节点的数量。但这让它变慢了。

代码语言:javascript
复制
import java.util.*;



class PrintCircuit{
    /**
     *
     * @param edges list of adjacent vertices for current edges
     * @return circuit in deque list
     */
    Deque makeEulerianCircuit(Deque[] edges, int numberOfNodes)
    {

        // return empty list for empty graph
        if (edges.length==0)
            return new LinkedList<>(); //empty graph

        // Stack for the path in the current iteration
        Deque currentPath = new ArrayDeque<>();

        // queue for the final circuit
        Deque circuit = new ArrayDeque<>();

        // start from any vertex
        currentPath.push(0);
        int currentVertexNumber = 0; // Current vertex

        while (!currentPath.isEmpty())
        {
            //if there are outgoing edges
            if (edges[currentVertexNumber].size() > 0)
            {
                currentPath.push(currentVertexNumber);
                int nextVertexNumber = edges[currentVertexNumber].pop();
                currentVertexNumber = nextVertexNumber;
            }

            // otherwise step back
            else
            {
                circuit.add(currentVertexNumber);
                currentVertexNumber = currentPath.pop();
            }
        }

        return circuit;

    }


    public static void main(String[] args)
    {

        PrintCircuit pc = new PrintCircuit();
        pc.inputAndPrintCircuit();

    }


    /**
     * Get the input, check to make sure the graph is even and run the printCircuit function
     */
    private void inputAndPrintCircuit(){
        Scanner scanner = new Scanner(System.in);
        int[] in = new int[2];
        in[0] = scanner.nextInt();
        in[1] = scanner.nextInt();
        Deque[] edges = new Deque[in[0]];
        for(int i=0;i();
        }

        // evenChecker is a Nx2 array where [0] = incoming edges and [1] = outgoing edges
        //should be equal or graph isn't Eulerian
        int[][] evenChecker = new int[in[0]][2];
        for (int i = 0; i < in[1]; i++) {
            int from = scanner.nextInt()-1;
            int to = scanner.nextInt()-1;
            evenChecker[from][0]++;
            evenChecker[to][1]++;
            edges[from].push(to);

        }
        if(!isGraphEven(evenChecker)){
            System.out.println("0");
            System.exit(0);
        } else {
            System.out.println("1");
        }
        Deque circuit = makeEulerianCircuit(edges, in[0]);
        while(circuit.size()>1){
            int nextNode = circuit.pollLast()+1;
            System.out.print(nextNode + " ");
        }
        System.out.println();
    }

    /**
     * checks to make sure that incoming edges = outgoing edges
     * @param evenChecker a Nx2 array where [0] = incoming edges and [1] = outgoing edges
     * @return true if incoming eges = outgoing edges, false otherwise
     */
    private boolean isGraphEven(int[][] evenChecker){
        for(int[] evenCheck:evenChecker){
            if(evenCheck[0]!=evenCheck[1]){
                return false;
            }
        }
        return true;
    }



}

有什么能让这件事更快的吗?更好的数据结构?更有效的算法?现在它没有通过我写它的作业,而且我想不出有什么办法使它更有效地工作。

更新:以下是分配的规范:

任务。给定有向图,在图或报告中找出不存在的欧拉圈。输入格式第一行分别包含整数n和m-顶点数和边数。以下m行中的每一行都指定了格式为“u”的边。(和往常一样,我们假设图的顶点是{1,2,。。。,(N)图可以包含自循环(即形式(v,v)的边)和平行边(即同一边的几个副本)。保证了图是强连通的。制约因素。1≤n≤104;n≤m≤105;1≤u,v≤n.输出格式。如果图没有欧拉循环,输出0。否则,第一行输出1和序列v1,v2,。。。,第二行中顶点的vm。此序列应遍历图中的欧拉循环:(v1,v2),(v2,v3),。。。,(vm−1,vm),(vm,−)都应该是图的边,图的每条边都应该在这个序列中出现一次。与往常一样,图可能包含许多欧拉圈(特别是,每个欧拉圈可能从其任意一个顶点开始遍历)。你可以输出其中的任何一个。

下面是一些示例输入:输入:

3 4 2 3 2 2 1 2 3

输出:

1 1 2 2 3

我还更新了上面的内容,包括了整个程序。

EN

回答 1

Code Review用户

发布于 2018-03-04 16:55:56

(通常考虑un_directed有限图的欧拉回路。)问题是标记为java --虽然所显示的代码的_syntax看起来是类型,但是变量处理看起来是Fortran。makeEulerianCircuit()(inputAndPrintCircuit)是实例成员--不必要。虽然有一个抽象输入& print可能很有用,但是让它打印一个非平凡算法的结果看起来很奇怪。指定并实现一个input()方法(并使用尝试使用资源处理输入)。inputAndPrintCircuit()将顶点数与问题语句不同--不要。为什么要有一个数组in[]来保存具有不同意义的输入值?只需使用nVerticesnEdges。同样,考虑使用nOutgoing[]nIncoming[]而不是二维数组。(给定输出边集合的恒定时间size(),您可以不使用nOutgoing[]。)正如我喜欢的代码注释一样:// empty graph是多余的(我会在条件语句之前删除注释,让// empty graph注释条件(稍微夸大问题--没有边的连通图仍然可能包含一个顶点;输入规范: nVertices≤nEdges))。您不需要int nextVertexNumber --直接将edges[currentVertexNumber].pop()分配给currentVertexNumber。我认为makeEulerianCircuit()依赖于指定一个(强)连通图的edges[]:它的doc注释应该反映这一点。

另一种设计将引入一个class Vertex,每个实例都包含可以从这个实例到达的各种其他顶点。

到目前为止,我还没有试图说服自己,makeEulerianCircuit()确实为每个连通的“偶数”图组装了一个欧拉电路--部分原因是问题中缺少测试支架。

Is there anything that can make this faster? Better data structures? A more efficient algorithm? --我认为这实现了O中的Hierholzer算法 (m)(在D24中稍微挥动一下手,就可以将m边加到ArrayDeque中,占用Θ(mlogm)时间--常量“永不”,从而使LinkedList变得更快)。(如果这是真的,就不应该有性能问题--我真的应该设置一个测试。)

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/188714

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档