热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

最小生成树总结

最小生成树算法:Prim算法和Kruskal算法prim算法:1).输入:一个加权连通图,其中顶点集合为V,边集合为E;2).初始化:Vnew{x},其中x为集合

最小生成树

算法: Prim算法和Kruskal算法

prim算法:

1).输入:一个加权连通图,其中顶点集合为V,边集合为E;

2).初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;

3).重复下列操作,直到Vnew = V:

a.在集合E中选取权值最小的边

#include
#include
#include
#include
#include
using namespace std;
#define INF 0x3f3f3f3f
#define MAXN 110
int map[MAXN][MAXN], lowcost[MAXN];
bool visit[MAXN];
int nodenum, sum;

void prim()
{
    int temp, k;
    sum = 0;
    memset(visit, false, sizeof(visit)); //初始化visit
    visit[1] = true;
    for(int i = 1; i <= nodenum; ++i) //初始化lowcost[i]
        lowcost[i] = map[1][i];
    for(int i = 1; i <= nodenum; ++i)//找生成树集合点集相连最小权值的边
    {
        temp = INF;
        for(int j = 1; j <= nodenum; ++j)
            if(!visit[j] && temp > lowcost[j])
                temp = lowcost[k = j];
        if(temp == INF) break;
        visit[k] = true; //加入最小生成树集合
        sum += temp;//记录权值之和
        for(int j = 1; j <= nodenum; ++j) //更新lowcost数组
            if(!visit[j] && lowcost[j] > map[k][j])
                lowcost[j] = map[k][j];
    }
}

int main()
{
    int a, b, cost, edgenum;
    while(scanf("%d", &nodenum) && nodenum)
    {
        memset(map, INF, sizeof(map));
        edgenum = nodenum * (nodenum - 1) / 2;
        for(int i = 1; i <= edgenum; ++i) //输入边的信息
        {
            scanf("%d%d%d", &a, &b, &cost);
            if(cost <map[a][b])
                map[a][b] = map[b][a] = cost;
        }
        prim();
        printf("%d\n", sum); //最小生成树权值之和
    }
    return 0;
}

练习题目:http://acm.hdu.edu.cn/showproblem.php?pid=1863

Kruskal算法:

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

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

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

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

详见博客:http://blog.csdn.net/lminy/article/details/50453675

代码实现:

自己习惯代码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
int pre[3000+10];
int n,m;
struct node
{
    int u,v,w;
}p[3000+10];
bool cmp(node x,node y)
{
    return x.wint Find(int x)
{
    if(pre[x]==x)
        return x;
    return pre[x]=Find(pre[x]);
}
void zuixiaoshu()
{
    for(int i=1;i<3000+10;i++)
        pre[i]=i;
    int sum=0,num=0;
    int flag=0;
    for(int i=1;i<=m;i++)
    {
        int x=Find(p[i].u);
        int y=Find(p[i].v);
        if(x!=y)//判断能不能不形成环
        {
            sum+=p[i].w;
            pre[x]=y;
            num++;
        }
        if(num==n-1)
        {
            flag=1;
            break;
        }
    }
    if(flag==0||m1)
        cout<<-1<else
    cout<int main()
{
    //int n,m;
    cin>>n>>m;//n个点,m条边
    for(int i=1;i<=m;i++)
    {
        //int a,b,c;
        cin>>p[i].u>>p[i].v>>p[i].w;
    }
    sort(p+1,p+1+m,cmp);//给边排序
    zuixiaoshu();
    return 0;
}

网上代码:

typedef struct          
{        
    char vertex[VertexNum];                                //顶点表 
    int edges[VertexNum][VertexNum];                       //邻接矩阵,可看做边表 
    int n,e;                                               //图中当前的顶点数和边数 
}MGraph; 

typedef struct node  
{  
    int u;                                                 //边的起始顶点 
    int v;                                                 //边的终止顶点 
    int w;                                                 //边的权值 
}Edge; 

void kruskal(MGraph G)  
{  
    int i,j,u1,v1,sn1,sn2,k;  
    int vset[VertexNum];                                    //辅助数组,判定两个顶点是否连通 
    int E[EdgeNum];                                         //存放所有的边 
    k=0;                                                    //E数组的下标从0开始 
    for (i=0;ifor (j=0;jif (G.edges[i][j]!=0 && G.edges[i][j]!=INF)  
            {  
                E[k].u=i;  
                E[k].v=j;  
                E[k].w=G.edges[i][j];  
                k++;  
            }  
        }  
    }     
    heapsort(E,k,sizeof(E[0]));                            //堆排序,按权值从小到大排列 
    for (i=0;i//初始化辅助数组 
    {  
        vset[i]=i;  
    }  
    k=1;                                                   //生成的边数,最后要刚好为总边数 
    j=0;                                                   //E中的下标 
    while (k//得到两顶点属于的集合编号 
        if (sn1!=sn2)                                      //不在同一集合编号内的话,把边加入最小生成树 
        {
            printf("%d ---> %d, %d",E[j].u,E[j].v,E[j].w);       
            k++;  
            for (i=0;iif (vset[i]==sn2)  
                {  
                    vset[i]=sn1;  
                }  
            }             
        }  
        j++;  
    }  
}  

推荐阅读
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 深入解析JVM垃圾收集器
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践》第二版,详细探讨了JVM中不同类型的垃圾收集器及其工作原理。通过介绍各种垃圾收集器的特性和应用场景,帮助读者更好地理解和优化JVM内存管理。 ... [详细]
  • 本文详细探讨了KMP算法中next数组的构建及其应用,重点分析了未改良和改良后的next数组在字符串匹配中的作用。通过具体实例和代码实现,帮助读者更好地理解KMP算法的核心原理。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • Docker的安全基准
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • PyCharm下载与安装指南
    本文详细介绍如何从官方渠道下载并安装PyCharm集成开发环境(IDE),涵盖Windows、macOS和Linux系统,同时提供详细的安装步骤及配置建议。 ... [详细]
  • 本题探讨了一种字符串变换方法,旨在判断两个给定的字符串是否可以通过特定的字母替换和位置交换操作相互转换。核心在于找到这些变换中的不变量,从而确定转换的可能性。 ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
author-avatar
卫凤莉_463
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有