最小生成树

青春壹個敷衍的年華 提交于 2020-04-04 17:44:17

有n个城市,给出了m条边,从m条边里面选n-1条边使得n个城市连通,且要求花费最小

样例输入:

6 9          (6个城市,9条边)
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2

输出样例:

19

Kruskal算法:

适用于稀疏图

思想:将所有的边从大到小排序,再遍历所有边,如果该边的两个点不在同一个集合,那么将该边加入最小生成树,直到加入n-1条边

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool vis[105];
long long a[1005];
int n,m,c=0;
long long ans;
struct edge{
    int u,v,w;
};
edge e[105];
bool cmp(edge e1,edge e2){               //边的排序 
    return e1.w<e2.w;
}
int getf(int v){                        //找祖先节点 
    if(a[v]==v){
        return v;
    }
    else{
        a[v]=getf(a[v]);
        return a[v]; 
    }
}
int merge(int u,int v){                 //判断是否将边加入最小生成树 
    int t1=getf(u);
    int t2=getf(v);
    if(t1!=t2){                            //边的两个点不在同一节点,则加入最小生成树 
        a[t2]=t1;
        return 1;
    }
    else{                                //否则不加入 
        return 0;
    }
}
int main() {
    cin>>n>>m;
    for(int i=1;i<=n;i++){                //初始化并查集数组 
        a[i]=i;
    }
    for(int i=0;i<m;i++){                //输入 
        cin>>e[i].u>>e[i].v>>e[i].w;
    }
    sort(e,e+m,cmp);                    //从小到大排序 
    for(int i=0;i<m;i++){
        if(merge(e[i].u,e[i].v)){        //判断边是否需要加入  加入就节点数+1 
            c++;
            ans+=e[i].w;
        }
        if(c==n-1){                        //只需要n-1条边即可 
            break;
        }
    }
    cout<<ans;
    return 0;
}

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!