1. 程式人生 > >最小生成樹(Kruskal)

最小生成樹(Kruskal)

#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
int flag = 0;
struct Edge{
	int u,v,w;
}edge[200005];
struct Node{
	int to,val;
};
vector<Node> node[200005];
int fa[5005],n,m,ans,eu,ev,cnt;
inline bool cmp(Edge a,Edge b)
{
    return a.w<b.w;
}
//快排的依據
inline int find(int x){
    if (x!=fa[x]) fa[x]=find(fa[x]);
    return fa[x];
}
//並查集迴圈實現模板,及路徑壓縮,
inline void kruskal()
{
    sort(edge,edge+m,cmp);
    //將邊的權值排序
    for(int i=0;i<m;i++)
    {
        eu=find(edge[i].u), ev=find(edge[i].v);
        if(eu==ev)
        {
            continue;
        }
        //建立一張新圖表示最小生成樹 
        node[edge[i].u].push_back(Node{edge[i].v,edge[i].w});
        //node[edge[i].v].push_back(Node{edge[i].u,edge[i].w});<—若是無向圖加上這行 
        //若出現環,則continue
        ans+=edge[i].w;
        //將此邊權計入答案
        fa[ev]=eu;
        if(++cnt==n-1)
        {
        	flag = 1;
            break;
        }
        //迴圈結束條件,及邊數為點數減一時
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        fa[i]=i;
    }
    //初始化並查集
    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
    }
    kruskal();
    if(flag)printf("%d\n",ans);
    else{
    	printf("-1\n");//不連通 
	}
    return 0;
}