【问题标题】:Kruskal's Algorith克鲁斯卡尔算法
【发布时间】:2020-04-23 10:20:51
【问题描述】:

我正在尝试实施 kruskal 的算法。与 bfs 和 dfs 一起。我编写了代码来打印邻接列表并显示 bfs 和 dfs,现在我面临着为 kruskal 算法编写代码的问题,我是使用地图和模板的新手。我不知道如何在 kruskals 算法中传递值,而且我经常出错。

这是我写的代码。

#include<iostream>
#include<map>
#include<queue>
#include<list>
#include<cstring>
#include<algorithm>

using namespace std;

template<typename T>

class Graph{

    private:
    map<T,list<pair<T,int>>>  l;

    void DFSHelper(T node,map<T,bool> &visited){

        cout<<node<<" -> ";
        visited[node]=true;

        for(auto neighbours:l[node]){

            if(!visited[neighbours.first]){

                DFSHelper(neighbours.first,visited);

            }
        }
    }

    public:

    void add(T A,T B,bool bi,int wi){

        l[A].push_back(make_pair(B,wi));

        if(bi == true){

            l[B].push_back(make_pair(A,wi));

        }
    }

    void print(){

        for(auto c:l){

            int c1 = c.first;

            list<pair<int,int>> n = c.second;

            cout<<c1<<" -> ";
            for(auto k:n){

                int dest = k.first;
                int dist = k.second;

                cout<<dest<<"("<<dist<<")  ";
            }
            cout<<endl;

        }     
    }

    void bfs(T src){

        map<T,bool> visited;
        queue<T> q;

        q.push(src);
        visited[src] = true;

        while(!q.empty()){

            T node = q.front();
            q.pop();
            cout<<node<<" -> ";
            for(auto children:l[node]){

                if(!visited[children.first]){

                    visited[children.first]=true;

                    q.push(children.first);

                }
            }
        }
    }

    void dfs(T src){

        map<T,bool> visited;
        int component = 1;

        DFSHelper(src,visited);

    }

    void cmp(T src,T end){

        return src.second.second<end.second.second;

    }

    void kruskals(){



    }
};

int main(){

    Graph<int> g;

    g.add(1,2,true,20);
    g.add(1,3,true,30);
    g.add(2,4,true,50);
    g.add(3,4,true,10);
    g.add(4,5,true,60);
    g.add(5,1,false,35);

    g.print();
    cout<<endl;
    cout<<"BFS :- ";
    g.bfs(1);
    cout<<endl;
    cout<<"DFS :- ";
    g.dfs(1);
    g.kruskals();

}

【问题讨论】:

    标签: c++ c++14 kruskals-algorithm


    【解决方案1】:

    由于单向边5-&gt;1,您的图表似乎是定向的。 Kruskal 算法仅适用于无向图。 (Why?)

    在 Kruskal 算法中,您需要按边权重的非递减顺序对边进行排序。因此,您可以与映射 l 一起维护一个额外的数据结构,并将其插入到 add() 函数中,或者在 kruskals() 函数本身中创建它。

    接下来你需要一个数据结构来查询图中的任意两个节点是否属于两个不同的组件。如果您可以通过仅考虑在 Kruskal 算法的特定迭代之前遇到的边来到达另一个节点,那么这里两个节点被称为在同一个组件中。 Disjoint Set Union 可以有效地做到这一点。

    这是一个实现,我使用集合edge_weights 来存储按权重排序的边:

    #include<iostream>
    #include<map>
    #include<queue>
    #include<list>
    #include<cstring>
    #include<algorithm>
    #include <set> // Added
    using namespace std;
    
    template<typename T>
    class DisjointSetUnion {
        map<T, T> parent; 
        map<T, int> sz; // stores sizes of component
     public:
        void make_set(T v) {
            parent[v] = v;
        }
        T find_set(T x) {
            if(x != parent[x]) parent[x] = find_set(parent[x]);
            return parent[x];
        }
        void merge_sets(T x, T y) {
            int px = find_set(x), py = find_set(y);
            if(sz[px] > sz[py]) parent[py] = px;
            else parent[px] = py;
            if(sz[py] == sz[px]) sz[py]++;
        }
    };
    
    template<typename T>
    class Graph{
     private:
        map<T,list<pair<T,int>>>  l;
        set<pair<int, pair<T, T>>> edge_weights; // no parallel (or duplicate) edges exist
        void DFSHelper(T node,map<T,bool> &visited){
    
            cout<<node<<" -> ";
            visited[node]=true;
    
            for(auto neighbours:l[node]){
    
                if(!visited[neighbours.first]){
    
                    DFSHelper(neighbours.first,visited);
    
                }
            }
        }
    
     public:
    
        void add(T A,T B,bool bi,int wi){
    
            l[A].push_back(make_pair(B,wi));
    
            if(bi == true){
    
                l[B].push_back(make_pair(A,wi));
                edge_weights.insert(make_pair(wi, make_pair(A, B))); // Added
            }
        }
    
        void print(){
    
            for(auto c:l){
    
                int c1 = c.first;
    
                list<pair<int,int>> n = c.second;
    
                cout<<c1<<" -> ";
                for(auto k:n){
    
                    int dest = k.first;
                    int dist = k.second;
    
                    cout<<dest<<"("<<dist<<")  ";
                }
                cout<<endl;
    
            }     
        }
    
        void bfs(T src){
    
            map<T,bool> visited;
            queue<T> q;
    
            q.push(src);
            visited[src] = true;
    
            while(!q.empty()){
    
                T node = q.front();
                q.pop();
                cout<<node<<" -> ";
                for(auto children:l[node]){
    
                    if(!visited[children.first]){
    
                        visited[children.first]=true;
    
                        q.push(children.first);
    
                    }
                }
            }
        }
    
        void dfs(T src){
    
            map<T,bool> visited;
            int component = 1;
    
            DFSHelper(src,visited);
    
        }
    
        void cmp(T src,T end){
    
            return src.second.second<end.second.second;
    
        }
    
        void kruskals(){
            DisjointSetUnion<int> dsu;
            // make singleton components of each node
            for(auto it: l) {
                T u = it.first;
                dsu.make_set(u);
            }
            // iterate over all edges in sorted order
            for(auto ed: edge_weights) {
                int w = ed.first;
                T u = ed.second.first, v = ed.second.second;
                // if they belong to different components then they are
                // part of the MST, otherwise they create a cycle
                if(dsu.find_set(u) != dsu.find_set(v)) {
                    // this edge is part of the MST, do what you want to do with it!
                    cout << "(" << u << "," << v << "," << w << "), ";
                    // merge the two different components
                    dsu.merge_sets(u, v);
                }
            }
        }
    };
    
    int main(){
    
        Graph<int> g;
    
        g.add(1,2,true,20);
        g.add(1,3,true,30);
        g.add(2,4,true,50);
        g.add(3,4,true,10);
        g.add(4,5,true,60);
        // Removed unidirectional edge below
        // g.add(5,1,false,35); 
    
        g.print();
        cout<<endl;
        cout<<"BFS :- ";
        g.bfs(1);
        cout<<endl;
        cout<<"DFS :- ";
        g.dfs(1);
        cout << endl;
        cout << "Edges in MST (u,v,w): ";
        g.kruskals();
        cout << endl;
    
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多