最小生成树 prim

来源:互联网 发布:苏州软件测试招聘 编辑:程序博客网 时间:2024/06/06 10:06

思想:
MST(Minimum Spanning Tree,最小生成树)问题有两种通用的解法,Prim算法就是其中之一,它是从点的方面考虑构建一颗MST,大致思想是:设图G顶点集合为U,首先任意选择图G中的一点作为起始点a,将该点加入集合V,再从集合U-V中找到另一点b使得点b到V中任意一点的权值最小,此时将b点也加入集合V;以此类推,现在的集合V={a,b},再从集合U-V中找到另一点c使得点c到V中任意一点的权值最小,此时将c点加入集合V,直至所有顶点全部被加入V,此时就构建出了一颗MST。因为有N个顶点,所以该MST就有N-1条边,每一次向集合V中加入一个点,就意味着找到一条MST的边。

过程:
http://blog.csdn.net/yeruby/article/details/38615045

这里写图片描述
测试用例:
输入:
6 10
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6
输出:
15

这里写图片描述

# include <iostream># include <cstdio># include <cstring>using namespace std;# define MAXN 1000# define INF 0x3f3f3f3f//这个可以与memset(数组名,INF,sizeof(数组名));  这样可以对数组的全部元素赋值为最大值 int map[MAXN][MAXN],lowcost[MAXN];bool visit[MAXN];int n,m,sum;//n节点  m边数  sum保存的是一个城市到另一个城市的最小权值 /*    map保存的是map[a][b] --->a到b的权值    lowcost数组保存的是一个城市到其余的城市的最小的权值     visit保存的是该节点是否被访问过 */void prim();int main(){    int a,b,cost;//a城市到b城市的权值为cost    while(scanf("%d%d",&n,&m)!=EOF){        memset(map,INF,sizeof(map));//map的每一个元素初始化为最大值         for(int i=1;i<=m;i++){            scanf("%d%d%d",&a,&b,&cost);            if(cost < map[a][b])                map[a][b] = map[b][a] = cost;        }        prim();         printf("%d\n",sum);    }    return 0;}void prim(){    int temp,k;    sum = 0;    memset(visit,false,sizeof(visit));//初始化visit 全部为false  证明该节点没有被访问过     visit[1] = true;//说明第一个节点已经被访问过    for(int i=1;i<=n;i++){//对lowcost初始化         lowcost[i] = map[1][i];    }     for(int i=1;i<=n;i++){//找生成树集合点集相连最小权值的边        temp = INF;        for(int j=1;j<=n;j++){//检索没有被访问的城市,而且权值最小的那个城市 ,并保存权值             if(!visit[j] && temp>lowcost[j]){                temp = lowcost[k=j];            }        }        if(temp == INF)//该节点与任何节点没有相连,             break;        visit[k] = true;//把这个城市加入最小生成树集合        sum+=temp; //记录权值之和        for(int j=1;j<=n;j++){//更新lowcost数组            if(!visit[j] && lowcost[j]>map[k][j]){                lowcost[j] = map[k][j];            }        }       } }
0 0