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

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

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

下面介绍两个算法。

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. java消息推送与接收

    package com.zl; import java.net.ServerSocket; import java.net.Socket; import org.apache.commons.mvc. ...

  2. .NET异常问题总结

    输入字符串的格式不正确. 有格式化字符替换符号{0}等,“{”和“}”作为特殊符号出现,如果有多余的“{”和“}”就会出错 GZIP压缩出现FF-F0-F1…是无效的输入流 要解压的字节流无效,可能是 ...

  3. 自动 点击切换 按钮切换 轮播无缝选项卡 ----原生js

    <!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...

  4. 14.高度最小的BST

    题目描述 对于一个元素各不相同且按升序排列的有序序列,请编写一个算法,创建一棵高度最小的二叉查找树. 给定一个有序序列int[] vals,请返回创建的二叉查找树的高度. 返回高度的代码如下: imp ...

  5. MyBatis学习总结(二)——使用MyBatis对表执行CRUD操作

    上一篇博文MyBatis学习总结(一)——MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对u ...

  6. safari渲染Transition动画不流畅问题

    用css3的transition过渡来做页面动画的时候,发现在chrome和ff流畅,在safari 不流畅: 度娘找到了淘宝UED的一个类似解决方案,动画就流畅了. 测试环境: win7 32bit ...

  7. linux 服务器登录显示lastlogin

    1.参数修改: /etc/ssh/sshd_config 问价里边的 printlastlog 设置为yes /etc/ssh/sshd_config 问价里边的 printmotd 设置为yes 2 ...

  8. zabbix通过curl命令判断web服务是否正常并自动重启服务

    zabbix通过curl命令判断web服务是否正常并自动重启服务 主要思路: 通过curl命令获取服务器响应码,如果正常返回200,不正常返回000 具体命令: curl -I -s -w " ...

  9. sql按字段值进行统计

    用group by 如有个student表里有性别sex来统计 select sex,count(*) from student group by sex;

  10. 2016.02.17 JS DOM编程艺术 第四五六章

    看完这三章内容,集中精力,加快速度.