前言:
先介紹一下最小生成樹。對於n個結點,用n-1條邊使它們相聯通,形成一棵樹,這個樹就叫生成樹,其中所有邊權值和最小的生成樹就是最小生成樹。
其次,介紹一下kruskal算法的思想。1.講所有邊按升序排序,2,選擇權值最小的邊。如果邊的兩個結點不在一個連通分量裏,就把一個結點的根節點作爲另一個結點的根節點的子節點;反之,在同一個連通分量中,忽略掉。3.重複第二步直到所有頂點都在一個連通分量中。
這裏,連通分量的判定和結點之間的合併用到了並查集。
問題:
還是暢通工程。
某省調查鄉村交通狀況,得到的統計表中列出了任意兩村莊間的距離。省政府“暢通工程”的目標是使全省任何兩個村莊間都可以實現公路交通(但不一定有直接的公路相連,只要能間接通過公路可達即可),並要求鋪設的公路總長度爲最小。請計算最小的公路總長度。
Input
測試輸入包含若干測試用例。每個測試用例的第1行給出村莊數目N ( < 100 );隨後的N(N-1)/2行對應村莊間的距離,每行給出一對正整數,分別是兩個村莊的編號,以及此兩村莊間的距離。爲簡單起見,村莊從1到N編號。
當N爲0時,輸入結束,該用例不被處理。
Output
對每個測試用例,在1行裏輸出最小的公路總長度。
Sample Input
3 1 2 1 1 3 2 2 3 4 4 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 0
Sample Output
3
5
代碼:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<string>
using namespace std;
const int maxn=100;
int n,sum;
int root[maxn];
struct Edge{
int l,r,cost;
bool operator < (const Edge &A) const{//ÖØÔØÔËËã·û£¬±ãÓÚÅÅÐò¡£
return cost<A.cost;
}
};
int findRoot(int x)
{
while(x!=root[x])
{
root[x]=root[root[x]];
x=root[x];
}
return x;
}
int unionRoot(Edge e)
{
int xx=findRoot(e.l);
int yy=findRoot(e.r);
if(xx!=yy)
{
root[yy]=xx;
sum+=e.cost;
}
}
int main()
{
while(cin>>n&&n!=0)
{
Edge edge[5000];
for(int i=0;i<n*(n-1)/2;i++)
cin>>edge[i].l>>edge[i].r>>edge[i].cost;
sort(edge,edge+n*(n-1)/2);
sum=0;
for(int i=1;i<=n;i++)
root[i]=i;
for(int i=0;i<n*(n-1)/2;i++)
unionRoot(edge[i]);
cout<<sum<<endl;
}
return 0;
}
結果:
總結:
時間複雜度:
O(eloge)
e:總邊數。