最小生成树算法C++语言实现

最小生成树算法C++语言实现

1. Prim

思想:选择离当前树最近的点来扩充当前树,直至边数为n-1。因为要从候选点中选择距离最近的点,直接实现比较困难,不如转换一下,选择当前最小生成树中的点向外延伸的边中最短的那条边,使用优先队列来维护向外延伸的边,实现起来比较简单。

#include 
using namespace std;
int n,m,a,b,v;
struct Edge{
     
    int fr,to,l;
    explicit Edge(int aa=0,int bb=0,int vv=0){
     fr=aa;to=bb;l=vv;}
    bool operator<(const Edge& o) const{
     
        return this->l>o.l;
    }
};
vector<Edge> graph[100010];
bool flag[100010]; // flag[i]==true means node i is in tree;
Edge tree[100010];
void Prim(){
     
    priority_queue<Edge> pq;
    flag[1]=true;
    int cnt=0;
    for(Edge e:graph[1]){
     pq.push(e);}
    while(cnt<n-1){
     
        Edge top=pq.top();pq.pop();
        if(flag[top.to]){
     continue;}
        flag[top.to]=true;
        tree[cnt++]=top;
        for(Edge e:graph[top.to]){
     
            if(!flag[e.to]){
     
                pq.push(e);
            }
        }
    }
}

int main(){
     
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=0;i<m;++i) {
     
        cin>>a>>b>>v;
        Edge e1(a,b,v),e2(b,a,v);
        graph[a].push_back(e1);
        graph[b].push_back(e2);
    }
    Prim();
    for(int i=0;i<n-1;++i){
     
        Edge e=tree[i];
        cout<<e.fr<<"->"<<e.to<<":"<<e.l<<endl;
    }
}

/**
5 7
1 2 6
1 3 1
1 4 7
2 3 2
2 4 5
3 4 3
3 5 4

 6 9
 1 2 2
 1 3 3
 2 3 6
 2 4 9
 2 5 5
 4 5 4
 3 5 1
 3 6 8
 5 6 7
 */

2. Kruskal

思想:贪心每次选择最小边,将两棵子树归并成一棵树,如果最小边的两个端点属于同一子树,则跳过该边。该场景符合并查集的使用场景,因此采用并查集实现。

#include 
using namespace std;
int n,m,a,b,v;
struct Edge{
     int fr,to,l;};
bool cmp(Edge e1, Edge e2){
     return e1.l<e2.l;}
Edge graph[100010];
Edge tree[100010];
int fa[100010];
int find(int x){
     return fa[x]==x?x:fa[x]=find(fa[x]);}
void merge(int x,int y){
     fa[find(x)]=find(y);}
void Kruskal(){
     
    for(int i=1;i<=n;++i){
     fa[i]=i;}  // init UnionSet
    sort(graph, graph+m,cmp);
    for(int i=0,j=0;i<n-1&&j<m;++j){
     
        Edge curr=graph[j];
        if(find(curr.fr)!=find(curr.to)){
     
            tree[i++]=curr;
            merge(curr.fr,curr.to);
        }
    }
}

int main(){
     
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=0;i<m;++i) {
     
        cin>>graph[i].fr>>graph[i].to>>graph[i].l;
    }
    Kruskal();
    for(int i=0;i<n-1;++i){
     
        Edge e=tree[i];
        cout<<e.fr<<"->"<<e.to<<":"<<e.l<<endl;
    }
}

你可能感兴趣的:(算法,算法,图论,c++)