zoukankan      html  css  js  c++  java
  • 最小生成树

    1.Kruskal算法

    A表示最小生成树所有边的集合.

    思路:将所有边按照权重从小到大排序,依次从中选择最小的边,若边的两个结点不在同一棵树中,就将这条边加入A.

    伪代码:

    Kruskal(G,w)
        A =for each vertex v in G.V
            MAKE-SET(v)//为每个结点建一棵树
        sort G.E into nondecreasing by weight
        for each edge(u,v) in G.E
            if FIND-SET(u) ≠ FIND-SET(v)
                A = A∪{(u,v)}
                UNION(u,v)//将u,v所在的树合并成一棵树
        return A

    时间复杂度:O(|E|lg|E|),又|E|<|V|2,有lg|E| = O(lg|V|),所以O(|E|lg|V|)

    编码实现:

    #include<iostream>
    #include<vector>
    #include<utility>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<cassert>
    #include<unordered_set>
    using namespace std;
    #define MAX 10000
    enum Color{white,gray,black};
    class Node{
    public:
        int index;
        Node* next=nullptr;//
        Node(int i):index(i){}
    };
    class VNode{
    public:
        char vertex;
        int index;
        int dist;
        int final;
        int indegree;
        Color color=white;
        int prev=-1;
        Node* firstNode=nullptr;
        VNode(char c,int i):vertex(c),index(i){}
    };
    typedef struct Graph{
        int EdgeNum;
        vector<VNode> Adj;
    }Graph;
    class Edge{
    public:
        int u;
        int v;
        int weight;
        Edge(int x,int y,int z):u(x),v(y),weight(z){}
    };
    bool cmp(Edge a,Edge b){
        return a.weight<b.weight;
    }
    vector<Edge> kruskal(const Graph &G,vector<Edge> &w){
        vector<Edge> A;
        vector<int> S;
        for(int i=0;i<G.Adj.size();i++){
            S.push_back(i);//初始化,下标表示结点,对应的值表示所属的树
        }
        sort(w.begin(),w.end(),cmp);
        for(int i=0;i<w.size();i++){
            if(S[w[i].u] != S[w[i].v]){
                A.push_back(w[i]);//将第i条边并入A,
                            //将所有和v在同一棵树中的结点都加入到u所在的树中
                int t=S[w[i].v];//t表示v所属的树
                //S[w[i].v] = S[w[i].u];
                for(int j=0;j<S.size();j++){
                    if(S[j] == t){
                        S[j] = S[w[i].u];
                    }
                }
                //S[w[i].v] = S[w[i].u];
            }
        }
        return A;
    }
    void AddEdge(Graph &G,int i,int j){
        Node* p = new Node(j);
        p->next = G.Adj[i].firstNode;
        G.Adj[i].firstNode = p;
    }
    int main(){
        Graph G;
        G.EdgeNum = 10;
        vector<char> v={'a','b','c','d','e','f'};
        for(int i=0;i<v.size();i++){
            G.Adj.push_back(VNode(v[i], i));
        }
        AddEdge(G,0,1);
        AddEdge(G,0,2);
        AddEdge(G,0,3);
        AddEdge(G,1,2);
        AddEdge(G,1,4);
        AddEdge(G,2,3);
        AddEdge(G,2,4);
        AddEdge(G,2,5);
        AddEdge(G,3,5);
        AddEdge(G,4,5);
        vector<Edge> w;//w中保存了所有边
        w.push_back(Edge(0,1,6));
        w.push_back(Edge(0,2,1));
        w.push_back(Edge(0,3,5));
        w.push_back(Edge(1,2,5));
        w.push_back(Edge(1,4,3));
        w.push_back(Edge(2,3,5));
        w.push_back(Edge(2,4,6));
        w.push_back(Edge(2,5,4));
        w.push_back(Edge(3,5,2));
        w.push_back(Edge(4,5,6));
        vector<Edge> A;
        A=kruskal(G,w);
        for(auto e:A){
            cout<<'['<<e.u<<','<<e.v<<']'<<'	'<<e.weight<<endl;
        }
        return 0;
    }
    View Code

    2.Prim算法

    A表示最小生成树所有结点的集合.

    思路:初始时选择一个根结点r,其余结点到r的距离初始化为MAX,将所有结点都压入最小优先队列Q,选择Q中到A最近的点加入A,重新计算Q中结点到A的距离,直到所有结点都加入A(即Q为空).

    伪代码:

    Prim(G,w,r)
        for each u in G.V
            u.key = MAX
            u.p = NIL
        r.key = 0
        Q = G.V//Q是以结点到A的距离为priority的最小优先队列
        while Q ≠ ∅
            u = EXTRACT-MIN(Q)
            for each v in G.Adj[u]
                if v in Q and w[u][v] < v.key
                    v.p = u
                    v.key = w[u][v]

    最小生成树是A = {(v,v.p):v∈V - {r}}

    时间复杂度:O(|E|lg|V|)

    编码实现:

    #include<iostream>
    #include<vector>
    #include<utility>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<cassert>
    using namespace std;
    #define MAX 10000
    enum Color{white,gray,black};
    class Node{
    public:
        int index;
        Node* next=nullptr;//
        Node(int i):index(i){}
    };
    class VNode{
    public:
        char vertex;
        int index;
        int dist;//key
        int final;
        int indegree;
        Color color=white;
        int prev=-1;
        Node* firstNode=nullptr;
        VNode(char c,int i):vertex(c),index(i){}
    };
    class Graph{
        int EdgeNum;
        vector<VNode> Adj;
    };
    struct comp
    {
        bool operator () (VNode &a,VNode &b) const {
            return a.dist>b.dist;
        }
    };
    bool belongQ(priority_queue<VNode,vector<VNode>,comp> Q,int v){
        while(!Q.empty()){
            VNode vn=Q.top();
            Q.pop();
            if(vn.index == v){
                return true;
            }
        }
        return false;
    }
    void prim(Graph &G,int w[][6],int r){
        for(int i=0;i<G.Adj.size();i++){
            G.Adj[i].dist = MAX;
            G.Adj[i].prev = -1;
        }
        G.Adj[r].dist = 0;
        priority_queue<VNode,vector<VNode>,comp> Q;
        for(int i=0;i<G.Adj.size();i++){
            Q.push(G.Adj[i]);
        }
        while(!Q.empty()){
            int u = (Q.top()).index;
            Q.pop();
            Node* p = G.Adj[u].firstNode;
            while(p != nullptr){
                int v = p->index;
                if(belongQ(Q,v) && (w[u][v]<G.Adj[v].dist)){
                    G.Adj[v].prev = u;
                    G.Adj[v].dist = w[u][v];
                }
                p = p->next;
            }
            priority_queue<VNode,vector<VNode>,comp> Q3;
                    while(!Q.empty()){
                        VNode vn=Q.top();
                        Q.pop();
                        Q3.push(G.Adj[vn.index]);
                    }
                    Q=Q3;
        }
    }
    void AddEdge(Graph &G,int i,int j,int weight,int w[][6]){
        Node* p = new Node(j);
        p->next = G.Adj[i].firstNode;
        G.Adj[i].firstNode = p;
        w[i][j]=weight;
    
        Node* p2 = new Node(i);
        p2->next = G.Adj[j].firstNode;
        G.Adj[j].firstNode = p2;
        w[j][i] = weight;
    }
    void print_path(Graph &G,int w[][6]){
        for(int i=1;i<G.Adj.size();i++){
            if(G.Adj[i].prev != -1){
                cout<<G.Adj[i].index+1<<","<<G.Adj[G.Adj[i].prev].index+1<<"	"<<w[i][G.Adj[i].prev]<<endl;
                //print_path(G,G.Adj[f].prev);
            }
        }
        
    }
    int main(){
        Graph G;
        G.EdgeNum = 10;
        vector<char> v={'a','b','c','d','e','f'};
        for(int i=0;i<v.size();i++){
            G.Adj.push_back(VNode(v[i], i));
        }
        int w[6][6];
        for (int i = 0; i < 6; ++i)
        {
            for (int j = 0; j < 6; ++j)
            {
                if(i != j){
                    w[i][j] = MAX;
                }
                else{
                    w[i][j] = 0;
                }
            }
        }
        AddEdge(G,0,1,6,w);
        AddEdge(G,0,2,1,w);
        AddEdge(G,0,3,5,w);
        AddEdge(G,1,2,5,w);
        AddEdge(G,1,4,3,w);
        AddEdge(G,2,3,5,w);
        AddEdge(G,2,4,6,w);
        AddEdge(G,2,5,4,w);
        AddEdge(G,3,5,2,w);
        AddEdge(G,4,5,6,w);
        prim(G,w,0);
        print_path(G,w);
        cout<<endl;    
        return 0;
    }
    View Code
  • 相关阅读:
    临时产品id记录
    一张图包含SEO一切要点
    Java基础之Volatile原理
    docker
    Linux设置虚拟内存教学和实战
    用最简单的话告诉你什么是ElasticSearch
    git全局配置修改
    数组和字符串方法区别
    git初级使用
    JavaScript的5中基本数据类型
  • 原文地址:https://www.cnblogs.com/bukekangli/p/4394870.html
Copyright © 2011-2022 走看看