最小生成树

最小生成树

A minimum spanning tree of a weighted, connected graph is a subgraph in which a tree connects all the vertices together and has the minimum weight.

Prime's Algorithm

Prime's algorithm is a greedy algorithm that finds a minimum spanning tree for a undirected graph.

algorithm description

  1. Starts from one vertex, select the least weight edge of that vertex;
  2. Add a new vertex that connects with the visited vertices with the least weight edge;
  3. Repeated until all vertices are visited

time complexity: O(|V|2)

Definition of Edge

class Edge{
    int from;
    int to;
    int weight;
    Edge(int u,int v,int w){
        from=u;
        to=v;
        weight=w;
    }
}

initialize a graph

public static ArrayList<ArrayList<Edge>> createGraph(Edge[] edges, int nodes)
    {
        ArrayList<ArrayList<Edge>> graph = new ArrayList<>();
        for(int i=0; i<nodes; i++)
            graph.add(new ArrayList<>());
        for(Edge source:edges) {
            Edge destination = new Edge(source.from, source.to, source.weight);
            graph.get(source.from).add(source);
            graph.get(source.to).add(destination);
        }
        return graph;
    }

Prime

PriorityQueue is an ordered queue. Here is used to store all the connected edges to visited nodes in increasing order (by weight).

public static ArrayList<Edge> prims(ArrayList<ArrayList<Edge>> graph){
        //to store MST
        ArrayList<Edge> MST = new ArrayList<>();
        //ordered queue, increasing order
        PriorityQueue<Edge> pq = new PriorityQueue<>((Edge edge1, Edge edge2) ->
        {
            if (edge1.weight < edge2.weight)
                return -1;
            else if(edge1.weight > edge2.weight)
                return 1;
            else
                return 0;
        });
        pq.addAll(graph.get(0));
        double cost = 0;
        boolean[] visited = new boolean[graph.size()];
        visited[0]=true;
        while(!pq.isEmpty()){
            Edge current=pq.poll();
            // if both nodes are visited, skip the round
            if(visited[current.to]&&visited[current.from])
                continue;
            for(Edge adjacency:graph.get(current.to)){
                if(!visited[adjacency.to])
                    pq.add(adjacency);
            }
            visited[current.to]=true;
            cost=cost+current.weight;
            MST.add(current);
        }
        return MST;
    }

 

Kruskal's Algorithm

algorithm description

  1. Sort the graph edges with respect to their weights in increasing order;
  2. Add edges to MST with least weight in a single round (make sure the added edges don't form a cycle--adding edges which only connect the disconnected components)

time complexity: O(|E|log|E|)

Pseudocode

MST- KRUSKAL (G, w)
  1. A ← ∅
  2. for each vertex v ∈ V [G]
  3.     do MAKE - SET (v)
  4.     sort the edges of E into non decreasing order by weight w
  5. for each edge (u, v) ∈ E, taken in non decreasing order by weight
  6.     do if FIND-SET (μ) ≠ if FIND-SET (v)
  7.     then A  ←  A ∪ {(u, v)}
  8.     UNION (u, v)
  9. return A

并查集的概念

function find() is to find the parent of one node, to make sure two nodes from different unions, and thus to check whether adding this edge will create a cycle.

function find() is to make two nodes have the same parent after their included edge is addpublic void kruskalMST(){

        PriorityQueue<Edge> pq = new PriorityQueue<>((Edge e1,Edge e2) -> {
            return Integer.compare(e1.weight,e2.weight);
        });
        pq.addAll(allEdges);
        int [] parent = new int[vertices];
        for (int i = 0; i <vertices ; i++) {
            parent[i] = i;
        }
        ArrayList<Edge> MST = new ArrayList<>();
        int index = 0;
        while(index<vertices-1){
            Edge edge = pq.poll();
            //check if adding this edge creates a cycle
            // two nodes must from different unions
            int x_set = find(parent, edge.from);
            int y_set = find(parent, edge.to);
            if(x_set!=y_set) {
                MST.add(edge);
                index++;
                union(parent, x_set, y_set);
            }
        }
    }

    public int find(int [] parent, int vertex){
        //chain of parent pointers from x upwards through the tree
        // until an element is reached whose parent is itself
        if(parent[vertex]!=vertex)
            return find(parent, parent[vertex]);;
        return vertex;
    }

    public void union(int [] parent, int x, int y){
        int x_set_parent = find(parent, x);
        int y_set_parent = find(parent, y);
        //make x as parent of y
        parent[y_set_parent] = x_set_parent;
    }

Summary

Prime starts from nodes. Generating MST by spanning edges from the visited nodes.

By contrast, Kruskal starts from edges, always choose the min weight edges and avoid cycles.

posted @ 2021-10-19 23:25  梦想家肾小球  阅读(27)  评论(0编辑  收藏  举报