Kruskal算法的基本思想:
1、先将图中的边按照权值(边长)从小到大排序
2、从排好序的边集合中每次选取一条边,只要选取的边不会构成回路就选择此边
3、重复2直到遍历完所有边
用一个数组T[N]表示每个顶点的父节点,初始化T[i] = -1 。 每次选择边的时候讲其中一个顶点的父节点设为边的另一顶点。使用递归函数压缩使每个顶点直接指向父节点,优化查询过程。若新加入边的两个顶点的父节点一致说明构成了回路,这条边丢弃。
示例代码:
#include<iostream>
#include<string>
#include<algorithm>
#include<windows.h>
#define N 1001
using namespace std;
struct edge
{
int v1,v2;
int distance;
};
int T[N];
struct edge way[N];
int findRoot(int x)
{
if(T[x] == -1)
{
return x;
}else
{
return T[x] = findRoot(T[x]); // 起到了路径压缩的作用,让顶点直接指向父节点
}
}
int cmp(edge a,edge b)
{
return a.distance < b.distance;
}
int main()
{
int n,m,i,j;
cin>>n>>m;
memset(T,-1,sizeof(T));
for(i = 1; i <= m; i++)
{
cin>>way[i].v1>>way[i].v2>>way[i].distance;
}
// 将边按权值从小到大排序
sort(way+1,way+1+m,cmp);
int ans = 0;
for(i = 1; i <= m; i++)
{
int x = findRoot(way[i].v1);
int y = findRoot(way[i].v2);
if(x != y) // 没有相同的父节点便不会构成回路
{
T[x] = y;
ans += way[i].distance;
}
}
int count = 0;
for(i = 1; i <= n; i++)
{
if(T[i] == -1)
{
count++;
}
}
if(count == 1)
{
cout<<"最短路径总长度:"<<ans<<endl;
}else
{
cout<<"图不联通的哦"<<endl;
}
system("pause");
return 0;
}
图的连通性判断,若最后还有一个以上的顶点的T[i] = -1,说明有孤立的点,即图不联通