Алгоритм Крускала - PullRequest
       33

Алгоритм Крускала

0 голосов
/ 23 апреля 2020

Я пытаюсь реализовать Kruskal's Al go. вместе с BFS и DFS. Я написал свой код, чтобы напечатать список адъюнктов и показать bfs и dfs, и теперь я столкнулся с проблемой при написании кода для алгоритма Крускала. Я вроде как новичок ie в использовании карт и шаблонов. Я не знаю, как передать значения в алгоритме 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();

}

1 Ответ

0 голосов
/ 29 апреля 2020

Ваш график выглядит направленным из-за однонаправленного края 5->1. Алгоритм Крускала работает только для неориентированных графов. ( Почему ?)

В алгоритме Крускала необходимо, чтобы ребра были отсортированы в неубывающем порядке весов ребер. Следовательно, вы можете сохранить дополнительную структуру данных вместе с картой l и вставить ее в функцию add() или создать ее в самой функции kruskals().

Далее вам потребуется структура данных для запроса если любые два узла графа принадлежат двум разным компонентам или нет. Здесь говорят, что два узла находятся в одном и том же компоненте, если вы можете достичь одного узла другим, рассматривая только ребра, встречающиеся до этой конкретной итерации алгоритма Крускала. Объединение несвязанных множеств может сделать это эффективно.

Вот реализация, где я использую набор 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;

}

...