最小生成树之Kruskal算法

来源:互联网 发布:mac 删除文件夹的命令 编辑:程序博客网 时间:2024/06/05 04:46

Kruskal算法的基本思想:

1、先将图中的边按照权值(边长)从小到大排序

2、从排好序的边集合中每次选取一条边,只要选取的边不会构成回路就选择此边

3、重复2直到遍历完所有边

用一个数组T[N]表示每个顶点的父节点,初始化T[i] = -1 。 每次选择边的时候讲其中一个顶点的父节点设为边的另一顶点。使用递归函数压缩使每个顶点直接指向父节点,优化查询过程。若新加入边的两个顶点的父节点一致说明构成了回路,这条边丢弃。

示例代码:

#include<iostream>#include<string>#include<algorithm>#include<windows.h>#define N 1001using 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,说明有孤立的点,即图不联通

0 0
原创粉丝点击