最小生成树

● 最小生成树的定义是给定一个无向图,如果它任意两个顶点都联通并且是一棵树,那么我们就称之为生成树(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包含所有图中的点。

P54-5.Prim算法_哔哩哔哩_bilibili

//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算法的更多相关文章

  1. 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。

    //归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...

  2. 最小生成树Prim算法(邻接矩阵和邻接表)

    最小生成树,普利姆算法. 简述算法: 先初始化一棵只有一个顶点的树,以这一顶点开始,找到它的最小权值,将这条边上的令一个顶点添加到树中 再从这棵树中的所有顶点中找到一个最小权值(而且权值的另一顶点不属 ...

  3. 最小生成树—prim算法

    最小生成树prim算法实现 所谓生成树,就是n个点之间连成n-1条边的图形.而最小生成树,就是权值(两点间直线的值)之和的最小值. 首先,要用二维数组记录点和权值.如上图所示无向图: int map[ ...

  4. Highways POJ-1751 最小生成树 Prim算法

    Highways POJ-1751 最小生成树 Prim算法 题意 有一个N个城市M条路的无向图,给你N个城市的坐标,然后现在该无向图已经有M条边了,问你还需要添加总长为多少的边能使得该无向图连通.输 ...

  5. SWUST OJ 1075 求最小生成树(Prim算法)

    求最小生成树(Prim算法) 我对提示代码做了简要分析,提示代码大致写了以下几个内容 给了几个基础的工具,邻接表记录图的一个的结构体,记录Prim算法中最近的边的结构体,记录目标边的结构体(始末点,值 ...

  6. 图论算法(五)最小生成树Prim算法

    最小生成树\(Prim\)算法 我们通常求最小生成树有两种常见的算法--\(Prim\)和\(Kruskal\)算法,今天先总结最小生成树概念和比较简单的\(Prim\)算法 Part 1:最小生成树 ...

  7. 最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析

    最小生成树,Prim算法与Kruskal算法,408方向,思路与实现分析 最小生成树,老生常谈了,生活中也总会有各种各样的问题,在这里,我来带你一起分析一下这个算法的思路与实现的方式吧~~ 在考研中呢 ...

  8. HDU1102 最小生成树prim算法

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1102 题意:给出任意两个城市之间建一条路的时间,给出哪些城市之间已经建好,问最少还要多少时间使所有的城 ...

  9. 最小生成树——prim算法

    prim算法是选取任意一个顶点作为树的一个节点,然后贪心的选取离这棵树最近的点,直到连上所有的点并且不够成环,它的时间复杂度为o(v^2) #include<iostream>#inclu ...

随机推荐

  1. mysql行锁、表锁。乐观锁,悲观锁

    锁定用于确保事务完整性和数据库一致性. 锁定可以防止用户读取其他用户正在更改的数据,并防止多个用户同时更改相同的数据. 如果不使用锁定,数据库中的数据可能在逻辑上变得不正确,而针对这些数据进行查询可能 ...

  2. java中的正则表达式And Pattern And Macher

    在哪里?? java.util.regex包下有两个用于正则表达式的类, 一个是Matcher类, 另一个Pattern 简单例子 public class RegexLeaning { public ...

  3. Redis 的内存用完了会发生什么?

    如果达到设置的上限,Redis 的写命令会返回错误信息(但是读命令还可以正 常返回.)或者你可以将 Redis 当缓存来使用配置淘汰机制,当 Redis 达到内存 上限时会冲刷掉旧的内容.

  4. 解释基于 XML Schema 方式的切面实现?

    在这种情况下,切面由常规类以及基于 XML 的配置实现.

  5. 32 位和 64 位的 JVM,int 类型变量的长度是多数?

    32 位和 64 位的 JVM 中,int 类型变量的长度是相同的,都是 32 位或者 4个字节.

  6. spring 支持哪些 ORM 框架?

    Hibernate iBatis JPA JDO· OJB

  7. 数据分析之Pandas操作

    Pandas pandas需要导入 import pandas as pd from pandas import Series,DataFrame import numpy as np 1 Serie ...

  8. vue中基于sortablejs与el-upload实现文件上传后拖拽排序

    今天做冒烟测试的时候发现商品发布有一个拖拽图片排序功能没做,赶紧加上 之前别的同事基于 vuedraggable 实现过这个功能,我这里自己深度封装了 el-upload ,用这种方式改动很大,而且感 ...

  9. js技术之input只读功能可以通过js设置readonly

    一.input标签 输入项标签,不同type属性,会有不同的显示效果和不同的作用 input标签的属性: disabled:表单项禁用,不可修改值,也不会被提交 readonly:表单项只读,不可修改 ...

  10. ctfhub 过滤运算符 综合过滤练习 读取源代码 远程包含 eval执行 文件包含 php://input

    过滤运算符 过滤了\和&那么尝试; 成功那么将flag cat出来 127.0.0.1;cat flag_27249269530391.php 得到flag 综合过滤练习 这次过滤有点多过滤了 ...