【ACM程序设计】最小生成树 Prim算法
最小生成树
● 最小生成树的定义是给定一个无向图,如果它任意两个顶点都联通并且是一棵树,那么我们就称之为生成树(Spanning Tree)。如果是带权值的无向图,那么权值之和最小的生成树,我们就称之为最小生成树(MST, Minimum Spanning Tree)。
● 求最小生成树的算法有很多,可以用Prim, Kuskual, Boruvka, 甚至遗传算法。这里介绍较为基础的两种Prim算法和Kuskual算法。
Prim算法
我们先建立两个点集,分别表示已经被加入到生成树中的点和还没有被加入到点集中的点分别记为集合V和集合T,一开始所有的点都在T集合中。
(1)我们将任意一个点从集合T置入集合V中。
(2)我们再在与集合V中的点连接的所有集合T的点中,找到一个点,使得这个点与集合V中的点的边最小,将这个点从集合T移动到集合V中。
(3)不断重复步骤(2),使得最终V包含所有图中的点。


//sum使用引用可以把数值传出函数
void Prim(int n, float MGraph[][n], int v0, float& sum)
{
int lowCost[n], vSet[n];
int v, k, min;
for (int i = 0; i < n; i++)
{
lowCost[i] = MGraph[v0][i]; //将首个要访问的节点与其他节点的距离填入lowcost数组
vSet[i] = 0; //所有节点都没有访问过
}
v = v0; //当前节点设置为初节点
vSet[v] = 1; //初节点设置为访问过
sum = 0;
//已经访问过一个节点了,要遍历剩下的n-1个节点
for (int i = 0; i < n - 1; i++)
{
//要寻找到lowcost数组中的最小值
min = INF;
for (int j = 0; j < n; j++)
{
//lowcost最小值且没有遍历过的
if(vSet[j] == 0 && lowCost[j] < min)
{
min = lowCost[j];
k = j; //记录下最小值的序号
}
}
vSet[k] = 1; //把那个最小路径的节点记录已访问
v = k; //当前节点设置为最小路径节点
sum += min;
//更新lowcost数组
for (int j = 0; j < n; ++j)
{
//将未访问过的节点且是新节点下一个位置比之前lowcost小的节点更新
if (vSet[j] == 0 && MGraph[v][j] < lowCost[j])
lowCost[j] = MGraph[v][j];
}
}
}
P3366 【模板】最小生成树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目描述
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz。
输入格式
第一行包含两个整数 N,M,表示该图共有 N 个结点和 M 条无向边。
接下来 M 行每行包含三个整数 Xi,Yi,Zi,表示有一条长度为 Zi 的无向边连接结点 Xi,Yi,Zi。
输出格式
如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz。
输入输出样例
输入
4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3
输出
7
输入
4 3
1 2 2
1 3 2
2 3 4
输出
orz
说明/提示
样例解释:

所以最小生成树的总边权为 2+2+3=7。
根据上述学习代码写出的题解:
#include <stdio.h>
int MGraph[5001][5001];
int vSet[5001];
int lowCost[5001];
int N;
#define INF 10000;
int Prim(int v0)
{
int v, k=0, min;
for (int i = 1; i <= N; i++)
{
lowCost[i] = MGraph[v0][i];
vSet[i] = 0;
}
v = v0;
vSet[v] = 1;
int sum = 0;
for (int i = 2; i <= N; i++)
{
min = INF;
for (int j = 1; j <= N; j++)
{
if (vSet[j] == 0 && lowCost[j] < min)
{
min = lowCost[j];
k = j;
}
}
vSet[k] = 1;
v = k;
sum += min;
for (int j = 1; j <= N; ++j)
{
if (vSet[j] == 0 && MGraph[v][j] < lowCost[j])
lowCost[j] = MGraph[v][j];
}
}
for (int i = 1; i <= N; i++)
if (vSet[i] == 0) return -1;
return sum;
}
int main(void) {
int i, j, k, dist;
int M;
scanf("%d %d", &N, &M);
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
MGraph[i][j] = INF;
if (i == j) MGraph[i][j] = 0;
}
}
for (i = 1; i <= M; i++) {
scanf("%d %d %d", &j, &k, &dist);
MGraph[j][k] = dist;
MGraph[k][j] = dist;
}
int res = Prim(1);
if (res == -1) printf("orz");
else printf("%d", res);
return 0;
}

课上给的题解,照着前面的思路改了变量名加了注释。
#include <stdio.h>
int MGraph[5001][5001];
int vSet[5001];
int lowCost[5001];
int N;
void Prim(int v0)
{
int i, j, k, cnt;
int mindis, v;
mindis = 0, v = v0;
for (i = 1; i <= N; i++)
{
vSet[i] = 0; //vSet置0
lowCost[i] = -1; //lowCost置-1
}
lowCost[v] = 0; //初始节点的lowcost置0
//开始遍历剩下的n-1个节点
for (cnt = 1; cnt < N && v; cnt++) {
vSet[v] = 1;
j = v, v = 0, mindis = 1000000001;
//遍历每个未访问过的节点更新lowcost数组
for (i = 1; i <= N; i++)
{
if (vSet[i]==0)
{
if (MGraph[j][i] != -1)
{
if (lowCost[i] == -1 || MGraph[j][i] < lowCost[i])
lowCost[i] = MGraph[j][i];
}
if (lowCost[i] != -1 && mindis > lowCost[i])
{
mindis = lowCost[i];
v = i;
}
}
}
}
if (cnt != N) printf("orz\n");
else {
long long ans = 0;
//累加lowcost数组即可得到最短路径
for (i = 1; i <= N; i++)
ans += lowCost[i];
printf("%lld\n", ans);
}
return;
}
int main(void) {
int i, j, k, dist;
int M;
scanf("%d %d", &N, &M);
//将初始邻接矩阵置-1
for (i = 1; i <= N; i++) {
for (j = 1; j <= N; j++) {
MGraph[i][j] = -1;
if (i == j) {
MGraph[i][j] = 0;
}
}
}
for (i = 1; i <= M; i++) {
scanf("%d %d %d", &j, &k, &dist);
if (MGraph[j][k] == -1 || MGraph[j][k] > dist) {
MGraph[j][k] = dist;
MGraph[k][j] = dist;
}
}
Prim(1);
return 0;
}
【ACM程序设计】最小生成树 Prim算法的更多相关文章
- 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。
//归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...
- 最小生成树Prim算法(邻接矩阵和邻接表)
最小生成树,普利姆算法. 简述算法: 先初始化一棵只有一个顶点的树,以这一顶点开始,找到它的最小权值,将这条边上的令一个顶点添加到树中 再从这棵树中的所有顶点中找到一个最小权值(而且权值的另一顶点不属 ...
- 最小生成树—prim算法
最小生成树prim算法实现 所谓生成树,就是n个点之间连成n-1条边的图形.而最小生成树,就是权值(两点间直线的值)之和的最小值. 首先,要用二维数组记录点和权值.如上图所示无向图: int map[ ...
- Highways POJ-1751 最小生成树 Prim算法
Highways POJ-1751 最小生成树 Prim算法 题意 有一个N个城市M条路的无向图,给你N个城市的坐标,然后现在该无向图已经有M条边了,问你还需要添加总长为多少的边能使得该无向图连通.输 ...
- SWUST OJ 1075 求最小生成树(Prim算法)
求最小生成树(Prim算法) 我对提示代码做了简要分析,提示代码大致写了以下几个内容 给了几个基础的工具,邻接表记录图的一个的结构体,记录Prim算法中最近的边的结构体,记录目标边的结构体(始末点,值 ...
- 图论算法(五)最小生成树Prim算法
最小生成树\(Prim\)算法 我们通常求最小生成树有两种常见的算法--\(Prim\)和\(Kruskal\)算法,今天先总结最小生成树概念和比较简单的\(Prim\)算法 Part 1:最小生成树 ...
- 最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析
最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析 最小生成树,老生常谈了,生活中也总会有各种各样的问题,在这里,我来带你一起分析一下这个算法的思路与实现的方式吧~~ 在考研中呢 ...
- HDU1102 最小生成树prim算法
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 题意:给出任意两个城市之间建一条路的时间,给出哪些城市之间已经建好,问最少还要多少时间使所有的城 ...
- 最小生成树——prim算法
prim算法是选取任意一个顶点作为树的一个节点,然后贪心的选取离这棵树最近的点,直到连上所有的点并且不够成环,它的时间复杂度为o(v^2) #include<iostream>#inclu ...
随机推荐
- synchronized使用及原理解析
修饰静态方法.实例方法.代码块 Synchronized修饰静态方法,对类对象进行加锁,是类锁. Synchronized修饰实例方法,对方法所属对象进行加锁,是对象锁. Synchronized修饰 ...
- java中的VO、PO、BO、DAO、POJO
针对java工程里的各种带O的对象,进行分析,了解各自的作用. PO: persistent object,持久对象.与数据库里表字段一一对应.PO是一些属性,以及set和get方法组成.一般情况下 ...
- 学习RabbitMQ(三)
1 用户注册后(会立即提示注册成功),过一会发送短信和邮件通知 发布/订阅模型 以上模式一般是用户注册成功后,写入一条数据到mysql,在发送一条消息到MQ! 如果不用消息中间件(或者简单的做成异步发 ...
- Three.js 实现3D开放世界小游戏:阿狸的多元宇宙 🦊
声明:本文涉及图文和模型素材仅用于个人学习.研究和欣赏,请勿二次修改.非法传播.转载.出版.商用.及进行其他获利行为. 背景 2545光年之外的开普勒1028星系,有一颗色彩斑斓的宜居星球 ,星际移民 ...
- DevEco Device Tool 3.0 Release 新版本发布,支持多人共享开发
DevEco Device Tool 是面向智能设备开发者提供的一站式集成开发环境,支持 HarmonyOS Connect 的组件按需定制,支持代码编辑.编译.烧录和调试.性能监测等功能,支持 C/ ...
- 阿里云场景化阿里云企业数字化转型售前方法PSA
阿里云场景化阿里云企业数字化转型售前方法PSA 目录 01 课程收获 理解企业数字化转型的概念.内涵.本质 了解企业数字化转型的要点.目标和切入点 掌握数字化转型项目售前阶段实践方法 场景化方案 阿里 ...
- 【译】客户端存储(Client-Side Storage)
本文转载自:众成翻译译者:文蔺链接:http://www.zcfy.cc/article/660原文:http://www.html5rocks.com/en/tutorials/offline/st ...
- python爬虫---爬取王者荣耀全部皮肤图片
代码: import requests json_headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win ...
- java中什么叫覆盖Override?请给实例
5.覆盖(Override) 马克-to-win:方法的覆盖(Override)是指子类重写从父类继承来的一个同名方法(参数.返回值也同). 例1.5.1-- class AAAMark_to_win ...
- PyQt5 基础知识(六):展示控件
目录 3. 展示控件 3.1 QLabel 3.1.1 描述 3.1.2 功能作用 3.1.2.1 基本功能 3.1.2.2 文本交互 3.1.2.3 内容操作 3.1.2.3.1 文本字符串 3.1 ...