最小生成树之prim算法与kruskal算法

给定一个带权值的无向图,那么权值之和最小的生成树,我们就称之为最小生成树(MST)。

(1)Prim算法是图论中的一种算法,可在加权连通图里搜索最小生成树。由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(Vertex (graph theory)),且其所有边的权值之和亦为最小。

算法代码及其注释如下(首先请参考代码下面的链接理解算法流程):

#include<iostream>  
#include<fstream>  
using  namespace std;  

#define MAX 100                 //暂时设图中一共有100个点
#define MAXCOST 0x7fffffff     //long int 里的最大值

int graph[MAX][MAX];         //图的邻接矩阵

int prim(int graph[][MAX], int n)   //最小生成树函数 
{  
    int lowcost[MAX];        //lowcost[i]的值为i点的权值
    int mst[MAX];            //mst[i]的值为与i点(终点)相连的那条边的另一个点(始点)
    int i, j, min, minid, sum = 0;  //min为当前次数预计连入最小生成树的最小权值(最小边的长度),minid为当前次数预计连入最小生成树的点,sum为当前次数最小生成树上权值之和
    for (i = 2; i <= n; i++)  
    {  
        lowcost[i] = graph[1][i];    //表示i点到1点(当前最小生成树)的权值(边的长度)
        mst[i] = 1;   //当前次数下与i点连接的边的另一个点都是1点
    }  
    mst[1] = 0;  //表示11点已经在最小生成树内
    for (i = 2; i <= n; i++)  
    {  
        min = MAXCOST;  
        minid = 0;      //每一次循环前恢复初始设定
        for (j = 2; j <= n; j++)  
        {  
            if (lowcost[j] < min && lowcost[j] != 0) //寻找与当前最小生成树相连的最小权值(最短的边长)与相连的点(j点),同时确保j点不在当前最小生成树内 
            {  
                min = lowcost[j];  
                minid = j;       //赋值
            }  
        }  
        cout << "V" << mst[minid] << "-V" << minid << "=" << min << endl;   //打印当前次数下由mst[minid]点接minid点,它们之间的边长(此时已确定为最短)min
        sum += min;  
        lowcost[minid] = 0;  //将此时的mind点放入最小生成树内
        for (j = 2; j <= n; j++)  
        {  
            if (graph[minid][j] < lowcost[j])  
            {  
                lowcost[j] = graph[minid][j];  //重新确定j点与当前最小生成树间的最小权值(最短的边长)
                mst[j] = minid;  //与j点相连的边的另一个点为minid点
            }  
        }  
    }  
    return sum;  
}  

int main()  
{  
    int i, j, k, m, n;  
    int x, y, cost;  
    ifstream in("input.txt");  
    in >> m >> n;//m=顶点的个数,n=边的个数  
    //初始化图G  
    for (i = 1; i <= m; i++)  
    {  
        for (j = 1; j <= m; j++)  
        {  
            graph[i][j] = MAXCOST;
            graph[j][i] = MAXCOST;     //假设图中的每两个顶点间的距离为无穷大
        }  
    }  
    //构建图G  
    for (k = 1; k <= n; k++)  
    {  
        in >> i >> j >> cost;   //输入两个点及这两点间的距离(权值)
        graph[i][j] = cost;  
        graph[j][i] = cost;  
    }  
    //调用最小生成树函数  
    cost = prim(graph, m);  
    //输出最小权值和  
    cout << "最小权值和=" << cost << endl;  
    system("pause");  
    return 0;  
}  

参考链接:
http://blog.csdn.net/yeruby/article/details/38615045

kruskal算法:
先构造一个只含 n 个顶点、而边集为空的子图,把子图中各个顶点看成各棵树上的根结点,之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,即把两棵树合成一棵树,反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直到森林中只有一棵树,也即子图中含有 n-1 条边为止。

参考链接:
http://blog.csdn.net/luomingjun12315/article/details/47700237
(注释较少看着吃力)(优推)

http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html
(从邻接矩阵的角度来看两种算法)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值