有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; }
来源:https://www.cnblogs.com/xusi/p/12632571.html