基本思想:node
假設連通網G=(V,E),令最小生成樹的初始狀態爲只有n個頂點而無邊的非連通圖T=(V,{}),圖中每一個頂點自成一個連通份量。c++
在E中選擇 代價最小 的邊,若該邊依附的頂點分別在T中不一樣的連通份量上,則將此邊加入到T中;不然,捨去此邊而選擇下一條代價最小的邊。依此類推,直至T中全部頂點構成一個連通份量爲止spa
時間複雜度爲O(eloge)(e爲圖中的邊數),因此,適合於求 稀疏圖 的最小生成樹。code
#include <bits/stdc++.h> #define MAXN 200005 using namespace std; int node,edge,ans=0,k=0; int fat[MAXN],siz[MAXN]; struct EDGE { int from,to,cost; } e[MAXN]; bool cmp(EDGE a,EDGE b) {return a.cost<b.cost;} int Find(int x){ return (fat[x]==x)? x : fat[x]=Find(fat[x]); } //查 路徑壓縮 //要麼是父節點,要麼就遞歸找到子節點,而且記錄下來,實現壓縮。 //注意:路徑壓縮後會破壞原有的父子關係。 void unionn(int x,int y)//並 { x=Find(x); y=Find(y); if(siz[x]>siz[y]) swap(x,y);//扁平樹 fat[x]=y; siz[y]+=siz[x]; } bool kruskal() { sort(e+1,e+edge+1,cmp); //貪心,排序 for(int i=1;i<=edge;++i) { if(k==node-1) break; if(Find(e[i].from) != Find(e[i].to)) { unionn(e[i].from,e[i].to); ans+=e[i].cost; ++k; } } return (k==node-1); } int main() { scanf("%d%d",&node,&edge); //node點數,edge邊數 for(int i=1;i<=edge;++i) scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].cost); //鄰接矩陣 for(int i=1;i<=node;++i) {fat[i]=i;siz[i]=1;} //初始化 siz[i]=1 這樣後面的累加有意義 if(kruskal()) printf("%d",ans); return 0; }