最小生成树

来源:互联网 发布:大白菜会计软件 编辑:程序博客网 时间:2024/06/07 02:10

以下介绍最小生成树的几个算法,Kruskal算法、Prim算法。
虽然网上有很多对于最小生成树的优质讲解,但是自己还是想写一下自己的理解与体会。
此处借用一下已有的经验(图解深深的吸引了我)。


Kruskal

先来讲一下kruskal算法,该算法的想法很简单,始终从未选取的边中选取最短的边并添加进去就好了。(此处未选取的边是指那些,边的任意一个顶点都没有被添加过),如有不明白的地方,请结合上面链接中的图解,进行推演并理解。
以下是模板:

/* *用边构图,也就是下面的Side结构体*/struct Side{    int from, to, wei;    bool operator < (const struct Side s)const {        return wei < s.wei;    }}side[MAXE];int kruskal(int n, int m){    int Min = 0, node = n - 1;    int root[MAXN];    for(int i = 0; i <= n; ++i) root[i] = i;    sort(side, side + sideNum);    for(int i = 0; node && i < sideNum; ++i) {        if(Union(side[i], root)) {            node--;            Min += side[i].wei;        }    }    return Min;}bool Union(const struct Side &s, int *root){    int p = Find(s.from, root);    int q = Find(s.to, root);    if(p != q) {        root[p] = q;        return true;    }    return false;}int Find(int p, int *root){    while(p != root[p]) {        root[p] = root[root[p]];        p = root[p];    }    return p;}

以上算法的贪心思想不难理解,然而对于贪心思想的正确性,此处运用了UnionFind数据结构。
这里写图片描述
正是UnionFind保证了选取边的时候,只考虑蓝边而忽略红边,从而可以得到生成树。

prim

prim算法与Dijstra算法相当类似,只是将原来的dist改为cost,用cost代表与该点相连的所有边中的最小权值。同样可以参照上面链接,进行推演理解。
以下是模板:

/* *此处采用的是邻接矩阵存储边的权值*/int prim(int N) {    int res = 0;    for(int i = 0; i < N; ++i)        cost[i] = INF, vis[i] = false;    cost[0] = 0;    while(true) {        int u = -1;        for(int v = 0; v < N; ++v) {            if(!vis[v] && (u == -1 || cost[v] < cost[u])) u = v;        }        if(u == -1) break;        vis[u] = true;        res += cost[u];        for(int v = 0; v < N; ++v) {            cost[v] = min(cost[v], Map[u][v]);        }    }    return res;}

这里推荐两个讲解次小生成树的链接,链接1,链接2。
次小生成树模板此处不给出,以后遇到题目再说吧。

0 0
原创粉丝点击