Prim算法最小生成树

来源:互联网 发布:linux 增加alias命令 编辑:程序博客网 时间:2024/06/05 03:55

学习本算法之前,先来回顾一下Dijistra算法的核心:用一个数组dis来记录源点到各个顶点的距离,然后每次扫描dis数组,从中选择出离源点最近的顶点,看通过该顶点为始点的边能否更新源点到其他各个顶点的距离。

这里我们对这个方法稍稍改变一下,便能得到prim算法的核心。在这里用dis数组记录生成树中到各个顶点的最短距离,也就是说现在的最短距离不是到源点的最短距离,而是到已经被选入生成树中顶点的最短距离,即如果选取点t加入生成树,

dis[k] > e[t][k],那么dis更新为e[t][k],而不是dis[k]+e[t][k]。

明白核心之后,我们便可以随便选择一个点加入最小生成树,因为最小生成树肯定包含图中所有的点的,然后更新dis中到生成树的最小距离,然后再选出最短的一个dis[i],然后看通过i点是否能更新生成树的到其余顶点的距离,然后重复操作,直至选择出n个点为止,算法结束。

#include <iostream>#include <cstdio>#define inf 11111using namespace std;struct note{int b, w, next;} edge[105];int head[105], book[105], no, dis[105];void init(int n){int i;for(i = 1; i <= n; ++i){book[i] = 0;head[i] = -1;}}void add(int a, int b, int w){edge[no].b = b;edge[no].w = w;edge[no].next = head[a];head[a] = no++;}int main(){int n, m, k, ans, ct, a, b, c, i, min, l;while(cin >> n >> m){init(n);no = 1;for(i = 1; i <= m; ++i){cin >> a >> b >> c;add(a, b, c);add(b, a, c);}for(i = 1; i <= n; ++i)dis[i] = inf;k = head[1];book[1] = 1;while(k != -1){if(!book[edge[k].b] && dis[edge[k].b] > edge[k].w)dis[edge[k].b] = edge[k].w;k = edge[k].next;}ct = 1;while(ct < n){min = inf+1;for(i = 1; i <= n; ++i){if(!book[i] && min > dis[i]){min = dis[i];l = i;}}++ct;book[l] = 1;ans += dis[l];k = head[l];while(k != -1){if(!book[edge[k].b] && dis[edge[k].b] > edge[k].w)dis[edge[k].b] = edge[k].w;k = edge[k].next;}}printf("%d\n", ans);}return 0;}

由堆优化的Dijistra算法,我们也会想能否通过堆来优化prim算法呢,其实是可以的,上代码。

#include <iostream>#include <cstdio>#include <queue>#define inf 11111using namespace std;struct node{int b,w;node(int b, int w){this->b = b;this->w = w;}bool operator<(node n) const{return this->w > n.w;}};struct note{int b, w, next;} edge[105];int head[105], book[105], no, dis[105];void init(int n){int i;for(i = 1; i <= n; ++i){dis[i] = inf;book[i] = 0;head[i] = -1;}}void add(int a, int b, int w){edge[no].b = b;edge[no].w = w;edge[no].next = head[a];head[a] = no++;}int main(){int n, m, k, ans, ct, a, b, c, i;while(cin >> n >> m){init(n);no = 1;for(i = 1; i <= m; ++i){cin >> a >> b >> c;add(a, b, c);add(b, a, c);}priority_queue<node> q;ans = 0;k = head[1];while(k != -1){q.push(node(edge[k].b, edge[k].w));dis[edge[k].b] = edge[k].w;k = edge[k].next;}ct = 1;book[1] = 1;while(ct < n){node x = q.top();q.pop();if(book[x.b]) continue;book[x.b] = 1;++ct;ans += x.w;k = head[x.b];while(k != -1){if(book[edge[k].b] == 0 && dis[edge[k].b] > edge[k].w){dis[edge[k].b] = edge[k].w;q.push(node(edge[k].b, edge[k].w));}k = edge[k].next;}}printf("%d\n", ans);}return 0;}

继续加油~


1 0
原创粉丝点击