简体   繁体   English

生成连接图Java

[英]Generate a Connected Graph java

I want to write a function, which is given a set of vertices and then develops an edge between 2 vertices and repeats this until the graph becomes a connected graph). 我想编写一个函数,该函数具有一组顶点,然后在2个顶点之间展开边并重复此过程,直到该图成为连接的图为止)。 How can I tell when the graph has become connected? 我如何知道图形何时已连接?

This would be a basic idea: Every time you add a new edge, you run BFS or DFS to check the connectivity. 这将是一个基本思想:每次添加新边缘时,您都运行BFS或DFS来检查连接性。 This solution is can be further optimized. 该解决方案可以进一步优化。

import java.util.Deque;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Random;
import java.util.Set;

import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleGraph;

public class Main {

public static boolean isConnected(SimpleGraph<Integer, DefaultEdge> graph) {
    Set<Integer> vertexSet = graph.vertexSet();
    if(vertexSet.size()==0) {
        //graph is connected by definition
        return true;
    }

    if(vertexSet.size()-1>graph.edgeSet().size()) {
        //not enough edges, must be disconnected
        return false;
    }

    Set<Integer> traversed = new HashSet<>();
    Deque<DefaultEdge> toTraverse = new LinkedList<DefaultEdge>();

    //pick one random element to start search
    Integer startVertex = vertexSet.iterator().next();

    traversed.add(startVertex);
    graph.edgesOf(startVertex).forEach(x->toTraverse.addLast(x));
    while(traversed.size()!=vertexSet.size() && toTraverse.size()!=0) {
        DefaultEdge currentEdge = toTraverse.pollFirst();
        Integer src = graph.getEdgeSource(currentEdge);
        Integer dst = graph.getEdgeSource(currentEdge);

        //it can be at most one new vertex
        Integer targetVertex = traversed.contains(src)?dst:src;
        if(!traversed.contains(targetVertex)) {
            traversed.add(targetVertex);
            //BFS
            graph.edgesOf(targetVertex).forEach(x->toTraverse.addLast(x));

            //DFS
            //graph.edgesOf(targetVertex).forEach(x->toTraverse.addFirst(x));
        }
    }

    if(traversed.size()==vertexSet.size()) {
        return true;
    }else {
        return false;
    }
}

public static SimpleGraph<Integer, DefaultEdge> buildGraph(int numberOfVertices) {
    SimpleGraph<Integer, DefaultEdge> g =
            new SimpleGraph<Integer, DefaultEdge>(DefaultEdge.class);
    for(int i = 0; i < numberOfVertices; i++) {
        g.addVertex(i);
    }
    Random r = new Random();
    do {
        int a = r.nextInt(numberOfVertices);
        int b = r.nextInt(numberOfVertices);
        while(a == b) {
            b = r.nextInt(numberOfVertices);
        }
        g.addEdge(a, b);
    }while(!isConnected(g));
    return g;

}

public static void main(String[] args) {
    SimpleGraph<Integer, DefaultEdge> g = buildGraph(10);
    System.out.println("Number of edges");
    System.out.println(g.edgeSet().size());
    System.out.println("Edges:");
    for(DefaultEdge e: g.edgeSet()){
        String a = g.getEdgeSource(e).toString();
        String b = g.getEdgeTarget(e).toString();
        System.out.println(a+" "+b);
    }
}

}

For an arbitrary graph, checking connectivity requires at least O(V) (V - number of vertices, E - number of edges). 对于任意图,检查连通性至少需要O(V)(V-顶点数,E-边数)。 BFS and DFS run in O(V+E). BFS和DFS在O(V + E)中运行。 This might be fine if you want to create relatively small graphs. 如果要创建相对较小的图形,这可能会很好。 Here is a smarter idea how to do it. 这是一个更聪明的想法。 At the beginning you create V separate graphs. 在开始时,您将创建V个独立的图。 Now you want to add edge between A and B, you find the graph where A belongs and the other where B belongs. 现在要在A和B之间添加边,您将找到A所属的图和B所属的另一个图。 If those are two different graphs, merge them. 如果这些是两个不同的图,请合并它们。 Repeat this process until only one graph remains. 重复此过程,直到只剩下一个图形。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM