典型例题:HDU 1233
#include<bits/stdc++.h>
using namespace std;
#define maxv 110
#define maxe 10010
#define ll long long
int tol=0;
struct edge
{
int a,b,w;
edge(int aa,int bb,int cc)
{
a=aa;
b=bb;
w=cc;
}
};
vector<edge> ve;
int F[maxv];
inline void add(int a,int b,int w)
{
ve.push_back(edge(a,b,w));
tol++;
}
bool cmp(edge e1,edge e2)
{
return e1.w<e2.w;
}
int find(int x)
{
if(F[x]==-1) return x;
else return F[x]=find(F[x]);
}
int Kruscal(int n)
{
int cnt=0;
ll ans=0;
memset(F,-1,sizeof(F));
sort(ve.begin(),ve.end(),cmp);
for(int i=0;i<tol;i++)
{
int u=ve[i].a;
int v=ve[i].b;
int w=ve[i].w;
int t1=find(u);
int t2=find(v);
if(t1!=t2||(t1==-1&&t2==-1))
{
F[t1]=t2;
cnt++;
ans+=w;
//cout<<u<<' '<<v<<endl;
}
if(cnt==n-1)
{
break;
}
}
if(cnt<n-1)
{
return -1;
}
return ans;
}
int main()
{
ios::sync_with_stdio(false);
int n;
while(cin>>n)
{
if(!n)
break;
ve.clear();
tol=0;
for(int i=0; i<n*(n-1)/2; i++)
{
int a,b,w;
cin>>a>>b>>w;
add(a,b,w);
}
cout<<Kruscal(n)<<endl;
}
return 0;
}
//////////////////////////
Kruscal的具体思路是将所有的边按权值从小到大排列,然后每次选择权值最小的且两个顶点不连通的边连起来,判断两个点是否连通利用并查集,可以在查询的过程中利用路径压缩提高查询效率,最后选取的边数等于n-1时停止,所有被选择的边构成了最小生成树。