最小生成树详解 prim+ kruskal代码模板

最小生成树概念:

一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边。 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。最小生成树其实是最小权重生成树的简称。

prim:

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

实现过程:

图例 说明 不可选 可选 已选(Vnew

此为原始的加权连通图。每条边一侧的数字代表其权值。 - - -

顶点D被任意选为起始点。顶点ABEF通过单条边与D相连。A是距离D最近的顶点,因此将A及对应边AD以高亮表示。 C, G A, B, E, F D

下一个顶点为距离DA最近的顶点。BD为9,距A为7,E为15,F为6。因此,FDA最近,因此将顶点F与相应边DF以高亮表示。 C, G B, E, F A, D
算法继续重复上面的步骤。距离A为7的顶点B被高亮表示。 C B, E, G A, D, F

在当前情况下,可以在CEG间进行选择。CB为8,EB为7,GF为11。E最近,因此将顶点E与相应边BE高亮表示。 C, E, G A, D, F, B

这里,可供选择的顶点只有CGCE为5,GE为9,故选取C,并与边EC一同高亮表示。 C, G A, D, F, B, E

顶点G是唯一剩下的顶点,它距F为11,距E为9,E最近,故高亮表示G及相应边EG G A, D, F, B, E, C

现在,所有顶点均已被选取,图中绿色部分即为连通图的最小生成树。在此例中,最小生成树的权值之和为39。 A, D, F, B, E, C, G

算法模板:

#include<stdio.h>
#include<string.h>
#define MAX 0x3f3f3f3f
int logo[101];//用来标记0和1  表示这个点是否被选择过
int map[101][101];//邻接矩阵用来存储图的信息
int dis[101];//记录任意一点到这个点的最近距离
int n;//点个个数
int prim()
{
    int i,j,now;
    int sum=0;
    /*初始化*/
    for(i=1; i<=n; i++)
    {
        dis[i]=MAX;
        logo[i]=0;
    }
    /*选定1为起始点,初始化*/
    for(i=1; i<=n; i++)
    {
        dis[i]=map[1][i];
    }
    dis[1]=0;
    logo[1]=1;
    /*循环找最小边,循环n-1次*/
    for(i=1; i<n; i++)
    {
        now=MAX;
        int min=MAX;
        for(j=1; j<=n; j++)
        {
            if(logo[j]==0&&dis[j]<min)
            {
                now=j;
                min=dis[j];
            }
        }
        if(now==MAX)
            break;//防止不成图
        logo[now]=1;
        sum+=min;
        for(j=1; j<=n; j++)//添入新点后更新最小距离
        {
            if(logo[j]==0&&dis[j]>map[now][j])
                dis[j]=map[now][j];
        }
    }
    if(i<n)
        printf("?\n");
    else
        printf("%d\n",sum);
}
int main()
{
    int a,b,c,d,m,i;
    while(scanf("%d",&n),n)//n是点数
    {
        m=n*(n-1)/2;//m是边数
        memset(map,0x3f3f3f3f,sizeof(map));//map是邻接矩阵存储图的信息
        for(i=0; i<m; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(c<map[a][b])//防止重边
                map[a][b]=map[b][a]=c;
        }
        prim();
    }
}

Kruskal算法:

1.概览

  Kruskal算法是一种用来寻找最小生成树的算法,在剩下的所有未选取的边中,找最小边,如果和已选取的边构成回路,则放弃,选取次小边。

2.实现过程

1).记Graph中有v个顶点,e个边

2).新建图Graphnew,Graphnew中拥有原图中相同的e个顶点,但没有边

3).将原图Graph中所有e个边按权值从小到大排序

4).循环:从权值最小的边开始遍历每条边 直至图Graph中所有的节点都在同一个连通分量中  if 这条边连接的两个节点于图Graphnew中不在同一个连通分量中   添加这条边到图Graphnew

  图例描述:

首先第一步,我们有一张图Graph,有若干点和边

将所有的边的长度排序,用排序的结果作为我们选择边的依据。这里再次体现了贪心算法的思想。资源排序,对局部最优的资源进行选择,排序完成后,我们率先选择了边AD。这样我们的图就变成了下图

在剩下的变中寻找。我们找到了CE。这里边的权重也是5

依次类推我们找到了6,7,7,即DF,AB,BE。

下面继续选择, BC或者EF尽管现在长度为8的边是最小的未选择的边。但是现在他们已经连通了(对于BC可以通过CE,EB来连接,类似的EF可以通过EB,BA,AD,DF来接连)。所以不需要选择他们。类似的BD也已经连通了(这里上图的连通线用红色表示了)。最后就剩下EG和FG了。当然我们选择了EG。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n, m,sum;
struct node
{
    int start,end,power;//start为起始点,end为终止点,power为权值
} edge[5050];
int pre[5050];

int cmp(node a, node b)
{
    return a.power<b.power;//按照权值排序
}

int find(int x)//并查集找祖先
{
    if(x!=pre[x])
    {
        pre[x]=find(pre[x]);
    }
    return pre[x];
}

void merge(int x,int y,int n)//并查集合并函数,n是用来记录最短路中应该加入哪个点
{
    int fx=find(x);
    int fy=find(y);
    if(fx!=fy)
    {
        pre[fx]=fy;
        sum+=edge[n].power;
    }
}
int main()
{
    while(~scanf("%d", &n), n)//n是点数
    {
        sum=0;
        m=n*(n-1)/2;//m是边数,可以输入
        int i;
        int start,end,power;
        for(i=1; i<=m; i++)
        {
            scanf("%d %d %d", &start, &end, &power);
            edge[i].start=start,edge[i].end=end,edge[i].power=power;
        }
        for(i=1; i<=m; i++)
        {
            pre[i]=i;
        }//并查集初始化
        sort(edge+1, edge+m+1,cmp);
        for(i=1; i <= m; i++)
        {
            merge(edge[i].start,edge[i].end,i);
        }
        printf("%d\n",sum);
    }
    return 0;
}
时间: 2024-12-30 18:09:22

最小生成树详解 prim+ kruskal代码模板的相关文章

hdu 1162 Eddy&#39;s picture 最小生成树入门题 Prim+Kruskal两种算法AC

Eddy's picture Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7428    Accepted Submission(s): 3770 Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to

最小生成树算法详解(prim+kruskal)

最小生成树概念: 一个有 n 个结点的连通图的生成树是原图的极小连通子图,且包含原图中的所有 n 个结点,并且有保持图连通的最少的边. 最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出.最小生成树其实是最小权重生成树的简称. prim: 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (graph theory)),且其所有边的权值之和亦为最小. p

Kruskal算法(二)之 C++详解

本章是克鲁斯卡尔算法的C++实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3. 克鲁斯卡尔算法图解 4. 克鲁斯卡尔算法分析 5. 克鲁斯卡尔算法的代码说明 6. 克鲁斯卡尔算法的源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树. 例如,对于如上图G4所示的

Prim算法(一)之 C语言详解

本章介绍普里姆算法.和以往一样,本文会先对普里姆算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 普里姆算法介绍 普里姆(Prim)算法,和克鲁斯卡尔算法一样,是用来求加权连通图的最小生成树的算法. 基本思想 对于图G而言,V是所

Kruskal算法(三)之 Java详解

前面分别通过C和C++实现了克鲁斯卡尔,本文介绍克鲁斯卡尔的Java实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3. 克鲁斯卡尔算法图解 4. 克鲁斯卡尔算法分析 5. 克鲁斯卡尔算法的代码说明 6. 克鲁斯卡尔算法的源码 转载请注明出处:http://www.cnblogs.com/skywang12345/ 更多内容:数据结构与算法系列 目录 最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的

【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解

喜欢的话可以扫码关注我们的公众号哦,更多精彩尽在微信公众号[程序猿声] 本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情况下,我们把图看成是一种由"顶点"和"边"组成的抽象网络.在各个"顶点"间可以由"边"连接起来,使两个顶点间相互关联起来.图的结构可以描述多种复杂的数据对象,

poj1861 最小生成树 prim &amp; kruskal

// poj1861 最小生成树 prim & kruskal // // 一个水题,为的只是回味一下模板,日后好有个照应不是 #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <iostream> using namespace std; const int MAX_N = 1008; const int INF =

最小生成树之Prim Kruskal算法(转)

最小生成树 首先,生成树是建立在无向图中的,对于有向图,则没有生成树的概念,所以接下来讨论的图均默认为无向图.对于一个有n个点的图,最少需要n-1条边使得这n个点联通,由这n-1条边组成的子图则称为原图的生成树.一般来说,一个图的生成树并不是唯一的(除非原图本身就是一棵树). 现在考虑带权图G,即图的边带权,则最小生成树就是在G中权值和最小的一颗生成树,显然最小生成树也不是唯一的,但是其权值唯一.有很多应用需要用到最小生成树的概念,比较直观的一个应用就是:有n个村庄,现在要在这些村庄之间修一些路

图的应用详解-数据结构

图的应用详解-数据结构 概述 最小生成树——无向连通图的所有生成树中有一棵边的权值总和最小的生成树 拓扑排序 ——由偏序定义得到拓扑有序的操作便是拓扑排序.建立模型是AOV网 关键路径——在AOE-网中有些活动可以并行地进行,所以完成工程的最短时间是从开始点到完成点的最长路径的长度,路径长度最长的路径叫做关键路径(Critical Path). 最短路径——最短路径问题是图研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径. 1.最小生成树 1.1 问题背景: