【最小生成树】Prim算法和Kruskal算法

来源:互联网 发布:vs2015 python 编辑:程序博客网 时间:2024/06/15 05:37
一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。简单来说就是假如有10个点,你可以用9条线把这10个点连起来,不漏掉任何一个点,然后这9条边的权值最小,就是**最小生成树**了,就是用*小于顶点个数-1的边*,连接所有点,权值最小。最小生成树可以用kruskal(克鲁斯卡尔)算法或Prim(普里姆)算法求出。 Prim算法和Kruskal算法都是基于下述性质:如果(u,v)是图中权值最小的边,则最小生成树中必包含此边。Kruskal算法是针对边来说的,而Prime算法是针对顶点的。分析Prim算法,该算法由两个并列的循环组成,第一个循环次数为vex_num(即顶点的个数n);第二个循环,外层循环的次数为n-1,内层的循环次数为n。所以总体来说,Prim的时间复杂度为O(n2),并且该算法与图中边数的多少无关,所以该算法适合于求边稠密的图的最小生成树。是一种贪心算法 。Kruskal算法:将图各边按照权值进行排序,之后每次选择一条边,要注意边不能构成回路。

现在只学会了Kruskal算法,Prim还不会,不过只会Kruskal也是可以解决问题的( • ̀ω•́ )✧

这位大牛有讲Prim算法的,可以看一看Prim:http://blog.csdn.net/niushuai666/article/details/6689295

大概框架是:

图中节点的存储
struct edge{
int u,v,w; //边的顶点,权值
}edges[10];
节点权值排序函数
qsort(edges, m, sizeof(edge), cmp)
合并两个节点函数
void merge(int a,int b)

具体一些的代码:还是要用到之前的并查集的知识 并查集:http://blog.csdn.net/rricky_/article/details/76576120

#include <iostream>#include <stdio.h>#include <stdlib.h>#include<algorithm>using namespace std;int parent[10];int n,m,num,sumWeight;int i,j;struct edge{    int u,v,w; //边的顶点,权值}edges[10];//初始化并查集void UFset(){    for(i=1; i<=n; i++) parent[i] = -1;}//查找i的根int find(int x){    if(x!=parent[x])    parent[x]=find(parent[x]);    else return parent[x];}//合并两个元素a,bvoid join(int x,int y){    int fx=find(x);    int fy=find(y);    if(fx!=fy)        {        parent[fx]=fy;        printf("加入边:%d %d,权值: %d\n", x,y,edges[i].w);        sumWeight += edges[i].w;        num ++;    }}void kruskal(){    sumWeight = 0;    num = 0;    int u,v;    UFset();    for(i=0; i<m; i++)    {        u = edges[i].u;        v = edges[i].v;        join(u,v);        if(num==n-1)        {            printf("最小生成树的权值之和为:%d \n", sumWeight);            break;        }    }}//比较函数,用户排序bool cmp(edge a,edge b){    return a.w<b.w;}int main() {    scanf("%d %d", &n, &m);    for(i=0; i<m; i++){        scanf("%d %d %d", &edges[i].u,  &edges[i].v,  &edges[i].w);    }     sort(edges,edges+m,cmp);    kruskal();}/*测试数据:6 101 2 6 1 3 11 4 52 3 52 5 33 4 53 5 63 6 44 6 25 6 6 */