最小二叉树常常用在找最短路径、最小花费等题目中。与之相关的算法有两种,Prim算法和Kruskal算法,比较常用的是Kruskal算法,而且Prim算法没怎么理解清楚,所以就写记一下Kruskal算法吧。
实现步骤: (T表示边的集合)
1.设T的初试状态是空集
2.当T中的边数小于n-1条时:
a.从E(G)中选择权值最小的边(u,v)并删除
b.若(u,v)不和T中的边一起构成回路,则将边(u,v)加入T中
典型的题目比较多,这里就以poj1258为例:
题目大意:Tom有n个农场,他要修建公路,是每个农场连接起来(直接或间接),并且要使公路长度之和最小,使花费最少。
代码实现:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define maxn 120
using namespace std;
typedef struct node
{
int u, v, len;
}p;
p edge[maxn*maxn];
int vexNum, s[maxn];
bool cmp(node a, node b)
{
if(a.len < b.len)
return true;
else
return false;
}
void build()
{
for(int i = 1; i<=vexNum; i++)
s[i] = i;
}
int Find(int k)
{
if(k == s[k]) return k;
else return Find(s[k]);
return s[k];
}
void Union(int a, int b)
{
s[a] = b;
}
int main()
{
int m;
while(~scanf("%d", &vexNum)){
build();
int temp = 0;
for(int i = 1; i<=vexNum; i++)
for(int j = 1; j<=vexNum; j++){
scanf("%d", &m);
edge[temp].u = i;
edge[temp].v = j;
edge[temp].len = m;
temp++;
}
sort(edge, edge+temp, cmp);//对农场之间的距离排序
int sum = 0, fa, fb;
for(int i = 0; i<temp; i++){
fa = Find(edge[i].u);
fb = Find(edge[i].v);
if(fa == fb) continue;//同一个点,或形成回路时继续循环
sum += edge[i].len;
Union(fa, fb);//对已经选取的点进行标记,当出现回路时,就会有有fa=fb
}
printf("%d\n", sum);
}
return 0;
}
相关题目:
hdu1683,
hdu1232,
hdu1875