最小生成树在一个图中可以有多个,但是如果一个图中边的权值互不相同的话,那么最小生成树只可能存在一个,用反证法很容易就证明出来了。

当然最小生成树也是一个图中包含所有节点的权值和最低的子图。

在一个图中权值最小的那个边一定在最小生成树中,如果一个图包含环,环中权值最大的边一定不在最小生成树中,还有就是连接图的任意两个划分的边中权值最短的那一条一定在最小生成树中。

下面介绍两个算法。

Prim算法

Prim算法就是以任意一个点为源点,将所有点分为两组,一组是已经在最小生成树上的点,另一组是还未在最小生成树上的点,最初只有源点在最小生成树上。图中一定存在这样的边:它们的一个顶点在最小生成树上,另一点不在最小生成树上,将这些边中权值最短的那一条以及所连接的点加入最小生成树,继续循环直至所有点都在最小生成树上为止。在具体实现中,可以用一个包含所有节点的辅助数组来记录,这个数组的每个元素包含该点到最小生成树的距离最短的边的权值和这条边的另一个端点(也就是已经在树上的那个点),如果这个点已经在最小生成树上了,权值就为0,这样每次往最小生成树上新加一个点的时候,就去检查所有与它相邻的点,如果那些相邻的点到新加的的距离小于到原先树中点的距离的话,就更新那些点在辅助数组中的信息。

int Prim(struct Graph *G, struct Vertex vertex_list[ ], int S){
    ;

    ; i < G->vertex_num; i++){
        if(S != i){
            vertex_list[i].adjacent_vertex = S;
            vertex_list[i].low_cost = G->map[S][i];
        }
        else{
            vertex_list[i].adjacent_vertex = -;
            vertex_list[i].low_cost = ;
        }
    }
    ; j < G->vertex_num; j++){
        min_cost = Infinity;
        ; i < G->vertex_num; i++){
             != vertex_list[i].low_cost&&min_cost > vertex_list[i].low_cost){
                min_cost = vertex_list[i].low_cost;
                tmp_index = i;
            }
        }
        sum += min_cost;
        vertex_list[tmp_index].low_cost = ;
        ; i < G->vertex_num; i++){
             != vertex_list[i].low_cost&&vertex_list[i].low_cost > G->map[tmp_index][i]){
                vertex_list[i].adjacent_vertex = tmp_index;
                vertex_list[i].low_cost = G->map[tmp_index][i];
            }
        }
    }

    return sum;
}

Kruskal算法

Kruskal算法就是将所有边按权值从小到大加入最小生成树中,并且保证不形成环,确定不形成环的方式类似于并查集。

int Kruskal(struct Graph *G){
    , i, j, sum = , tmp, tmp_1, tmp_2;
    int vertex_list[G->vertex_num];
    struct Edge edge_list[G->edge_num];

    ; i < G->vertex_num; i++){
        vertex_list[i] = i;
    }
    ; i < G->vertex_num; i++){
        for(j = i; j < G->vertex_num; j++){
            if(Infinity != G->map[i][j]){
                edge_list[index].start = i;
                edge_list[index].end = j;
                edge_list[index].weight = G->map[i][j];
                index++;
            }
        }
    }
    qsort(edge_list, G->edge_num, sizeof(struct Edge), comp);
    ; i < G->edge_num; i++){
        if(vertex_list[edge_list[i].start] != vertex_list[edge_list[i].end]){
            ; j < G->vertex_num; j++){
                if(vertex_list[j] == vertex_list[edge_list[i].end]){
                    vertex_list[j] = vertex_list[edge_list[i].start];
                }
            }

            sum += edge_list[i].weight;
            printf("%d %d\n", edge_list[i].start, edge_list[i].end);
        }
    }

    return sum;
}

下面是完整代码,我也没怎么测过。

//
//  main.c
//  Minimum Spanning Tree
//
//  Created by 余南龙 on 2016/11/27.
//  Copyright © 2016年 余南龙. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>

#define MAXV 100
#define Infinity 10000000

struct Vertex{
    int adjacent_vertex;
    int low_cost;
};

struct Edge{
    int start;
    int end;
    int weight;
};

struct Graph{
    int map[MAXV][MAXV];
    int edge_num;
    int vertex_num;
};

int comp(const void *a, const void *b){
    struct Edge *pa = (struct Edge *)a;
    struct Edge *pb = (struct Edge *)b;
    if(pa->weight < pb->weight){
        ;
    }
    else{
        ;
    }
}

int Prim(struct Graph *G, struct Vertex vertex_list[ ], int S){
    ;

    ; i < G->vertex_num; i++){
        if(S != i){
            vertex_list[i].adjacent_vertex = S;
            vertex_list[i].low_cost = G->map[S][i];
        }
        else{
            vertex_list[i].adjacent_vertex = -;
            vertex_list[i].low_cost = ;
        }
    }
    ; j < G->vertex_num; j++){
        min_cost = Infinity;
        ; i < G->vertex_num; i++){
             != vertex_list[i].low_cost&&min_cost > vertex_list[i].low_cost){
                min_cost = vertex_list[i].low_cost;
                tmp_index = i;
            }
        }
        sum += min_cost;
        vertex_list[tmp_index].low_cost = ;
        ; i < G->vertex_num; i++){
             != vertex_list[i].low_cost&&vertex_list[i].low_cost > G->map[tmp_index][i]){
                vertex_list[i].adjacent_vertex = tmp_index;
                vertex_list[i].low_cost = G->map[tmp_index][i];
            }
        }
    }

    return sum;
}

int Kruskal(struct Graph *G){
    , i, j, sum = , tmp, tmp_1, tmp_2;
    int vertex_list[G->vertex_num];
    struct Edge edge_list[G->edge_num];

    ; i < G->vertex_num; i++){
        vertex_list[i] = i;
    }
    ; i < G->vertex_num; i++){
        for(j = i; j < G->vertex_num; j++){
            if(Infinity != G->map[i][j]){
                edge_list[index].start = i;
                edge_list[index].end = j;
                edge_list[index].weight = G->map[i][j];
                index++;
            }
        }
    }
    qsort(edge_list, G->edge_num, sizeof(struct Edge), comp);
    ; i < G->edge_num; i++){
        if(vertex_list[edge_list[i].start] != vertex_list[edge_list[i].end]){
            ; j < G->vertex_num; j++){
                if(vertex_list[j] == vertex_list[edge_list[i].end]){
                    vertex_list[j] = vertex_list[edge_list[i].start];
                }
            }

            sum += edge_list[i].weight;
            printf("%d %d\n", edge_list[i].start, edge_list[i].end);
        }
    }

    return sum;
}

void Init(struct Graph *G){
    int i, j, start, end, weight;

    scanf("%d%d", &(G->edge_num), &(G->vertex_num));
    ; i < G->vertex_num; i++){
        ; j < G->vertex_num; j++){
            G->map[i][j] = Infinity;
        }
    }
    ; i < G->edge_num; i++){
        scanf("%d%d%d", &start, &end, &weight);
        G->map[start][end] = G->map[end][start] = weight;
    }
}

void Output(struct Vertex vertex_list[ ], int size){
    int i;

    ; i < size; i++){
        printf("%d %d\n", i, vertex_list[i].adjacent_vertex);
    }
}

int main(){
    struct Graph G;
    struct Vertex *vertex_list;
    int sum;

    Init(&G);
    vertex_list = (struct Vertex*)malloc(sizeof(struct Vertex) * G.vertex_num);
    sum = Prim(&G, vertex_list, );
    printf("%d\n", sum);
    Output(vertex_list, G.vertex_num);
    sum = Kruskal(&G);
    printf("%d\n", sum);
}

Prim算法和Kruskal算法(图论中的最小生成树算法)的更多相关文章

  1. 转载:最小生成树-Prim算法和Kruskal算法

    本文摘自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/30/2615542.html 最小生成树-Prim算法和Kruskal算法 Prim算 ...

  2. 最小生成树之Prim算法和Kruskal算法

    最小生成树算法 一个连通图可能有多棵生成树,而最小生成树是一副连通加权无向图中一颗权值最小的生成树,它可以根据Prim算法和Kruskal算法得出,这两个算法分别从点和边的角度来解决. Prim算法 ...

  3. java实现最小生成树的prim算法和kruskal算法

    在边赋权图中,权值总和最小的生成树称为最小生成树.构造最小生成树有两种算法,分别是prim算法和kruskal算法.在边赋权图中,如下图所示: 在上述赋权图中,可以看到图的顶点编号和顶点之间邻接边的权 ...

  4. 最小生成树——Prim算法和Kruskal算法

    洛谷P3366 最小生成树板子题 这篇博客介绍两个算法:Prim算法和Kruskal算法,两个算法各有优劣 一般来说当图比较稀疏的时候,Kruskal算法比较快 而当图很密集,Prim算法就大显身手了 ...

  5. 最小生成树Prim算法和Kruskal算法

    Prim算法(使用visited数组实现) Prim算法求最小生成树的时候和边数无关,和顶点树有关,所以适合求解稠密网的最小生成树. Prim算法的步骤包括: 1. 将一个图分为两部分,一部分归为点集 ...

  6. Prim算法和Kruskal算法

       Prim算法和Kruskal算法都能从连通图找出最小生成树.区别在于Prim算法是以某个顶点出发挨个找,而Kruskal是先排序边,每次选出最短距离的边再找. 一.Prim(普里姆算法)算法: ...

  7. 【数据结构】最小生成树之prim算法和kruskal算法

    在日常生活中解决问题经常需要考虑最优的问题,而最小生成树就是其中的一种.看了很多博客,先总结如下,只需要您20分钟的时间,就能完全理解. 比如:有四个村庄要修四条路,让村子能两两联系起来,这时就有最优 ...

  8. Prim算法和Kruskal算法的正确性证明

    今天学习了Prim算法和Kruskal算法,因为书中只给出了算法的实现,而没有给出关于算法正确性的证明,所以尝试着给出了自己的证明.刚才看了一下<算法>一书中的相关章节,使用了切分定理来证 ...

  9. 最小生成树---Prim算法和Kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

  10. prim 算法和 kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

随机推荐

  1. php iquery

    <?php/** * */function iQuery($sql) { $dbcon = mysqli_connect("localhost", "root&qu ...

  2. python编码-1

    help帮助系统,一个好的方法是直接看自带的帮助,尽量不用baidu help()是进入交互式帮助界面 quit是退出交互式帮助界面 [root@kvm1 python]# python Python ...

  3. 处理畅捷通的T+ 12.0版,web服务无故自动停止的问题

    用了几个月的畅捷通T+ 12.0版,一直都挺正常,但最近这两周,出现了好几次web服务自动停止的情况,今天抽空仔细看了Windows的日志,发现在半夜2点左右,TPlusProWebService12 ...

  4. 打印心形---print 的基础使用

    #!/bin/usr/env python#coding=utf-8'''用学习到的print语句,完成如下图形的打印工作打印心形'''print " *** *** "print ...

  5. 每日学习心得:SharePoint 2013 自定义列表项添加Callout菜单项、文档关注、SharePoint服务端对象模型查询

    前言: 前一段时间一直都比较忙,没有什么时间进行总结,刚好节前项目上线,同时趁着放假可以好好的对之前遇到的一些问题进行总结.主要内容有使用SharePoint服务端对象模型进行查询.为SharePoi ...

  6. NODEJS - express

    1.express组织结构 app demo    |---node_modules------用于安装本地模块.     |---public------------用于存放用户可以下载到的文件,比 ...

  7. 【javascript基础】7、继承

    前言 由于本人水平有限,所以有些高手觉得现在写的内容偏容易,要一点点来嘛,今天和大家学习或者复习一下javascript的继承.我也就是尽量写吧······ 继承 javascript的继承其实主要就 ...

  8. Mysql备份迁移——MySqlBackup(.net)——(无法解决视图嵌视图报错)

    这里是利用MySqlBackup,可以再nuget中下载. 无法解决视图嵌视图报错的问题,只导表跟数据比较合适,如果有视图嵌视图,请参照Mysql备份迁移——Mysqldump(.NET调用Mysql ...

  9. J-Link clone问题

    在上一篇<修复山寨版的J-Link>,中已经介绍了恢复的步骤. 但是,在使用J-Link驱动(V4.94J)升级后,会出现下面情况. The connected emulator is a ...

  10. 【转】web测试总结

    1.字符型输入框: (1)字符型输入框:英文全角.英文半角.数字.空或者空格.特殊字符“~!@#¥%……&*?[]{}”特别要注意单引号和&符号.禁止直接输入特殊字符时,使用“粘贴.拷 ...