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

最小生成樹(MST)

Kraskal演算法

1.初始所有節點都獨立
2.按照邊的權值遞增遍歷所有的邊,若遍歷到的邊上的兩個點,分屬在不同的集合,則這條邊就是最小生成樹上的一條邊,並將這兩個頂點合併。
3.如果出現集合數量只為1個,說明最小生成樹已經構成。如果遍歷完所有的邊,集合還大於1個,說明原圖不連通,最小生成樹不存在。

程式碼

/*
題目描述:
    省政府“暢通工程”的目標是使全省任何兩個村莊間都可以實現公路交通(但不一定有直接的公路相連,只要能間接通過公路可達即可)。現得到城鎮道路統計表,表中列出了任意兩城鎮間修建道路的費用,以及該道路是否已經修通的狀態。現請你編寫程式,計算出全省暢通需要的最低成本。
輸入:
    測試輸入包含若干測試用例。每個測試用例的第1行給出村莊數目N ( 1< N < 100 );隨後的 N(N-1)/2 行對應村莊間道路的成本及修建狀態,每行給4個正整數,分別是兩個村莊的編號(從1編號到N),此兩村莊間道路的成本,以及修建狀態:1表示已建,0表示未建。

    當N為0時輸入結束。
輸出:
    每個測試用例的輸出佔一行,輸出全省暢通需要的最低成本。
樣例輸入:
3
1 2 1 0
1 3 2 0
2 3 4 0
3
1 2 1 0
1 3 2 0
2 3 4 1
3
1 2 1 0
1 3 2 1
2 3 4 1
0
樣例輸出:
3
1
0

*/
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; struct edge{ int a , b ,cost; bool operator < (const edge b)const{ return cost<b.cost; } }e[100*99/2]; int Tree[100],nodecount,ans; int findRoot(int a){ if(Tree[a]==-1){ return
a; } int root = findRoot(Tree[a]); Tree[a] = root; return root; } void unit(edge e){ int a_root = findRoot(e.a); int b_root = findRoot(e.b); if(a_root!=b_root){ Tree[a_root] = b_root; ans += e.cost; nodecount --; } } int main(){ int N,a,b,cost,status; while
(cin>>N&&N){ nodecount = N; ans = 0; for(int i=1;i<=N;i++){ Tree[i]=-1; } int M = N*(N-1)/2; for(int j=0;j<M;j++){ cin>>a>>b>>cost>>status; e[j].a = a; e[j].b = b; if(status) e[j].cost = 0; else e[j].cost = cost; } sort(e,e+M); for(int m=0;m<M;m++){ unit(e[m]); if(nodecount==1) break; } printf("%d\n",ans); } return 0; }