最小生成樹(MST)
阿新 • • 發佈:2018-12-24
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;
}