本文通过具体的算法模板题,给出Prim和Kruskal两种求解最小生成树求解过程和代码~

由浅入深,通俗易懂

题目选自洛谷P3366

题目描述

如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出 orz

输入格式

第一行包含两个整数 N,M,表示该图共有 N 个结点和 M 条无向边。

接下来 M 行每行包含三个整数 Xi​,Yi​,Zi​,表示有一条长度为Zi​ 的无向边连接结点 Xi​,Yi​。

输出格式

如果该图连通,则输出一个整数表示最小生成树的各边的长度之和。如果该图不连通则输出 orz

输入输出样例

输入 1

4 5
1 2 2
1 3 2
1 4 3
2 3 4
3 4 3

输出 1

7

说明/提示

数据规模:

对于 20% 的数据,N≤5,M≤20。

对于 40% 的数据,N≤50,M≤2500。

对于 70% 的数据,N≤500,M≤104。

对于 100% 的数据:1≤N≤5000,1≤M≤2×10^5,1≤Zi​≤10^4。

前言

两者区别:Prim在稠密图中比Kruskal优,在稀疏图中比Kruskal劣。Prim是以更新过的节点的连边找最小值,Kruskal是直接将边排序。

两者其实都是运用贪心的思路

Prim算法思想:

Prim的思想是将任意节点作为根,再找出与之相邻的所有边(用一遍循环即可),再将新节点更新并以此节点作为根继续搜,维护一个数组:dis,作用为已用点到未用点的最短距离。

具体算法流程图解如下:

优化:

但是!由于该题数据比较大,我们应该做一些优化

例如Prim可以用优先队列(也即 堆)来优化算法

Kruskal算法思想:

Kruskal算法的思想比Prin好理解一些。先把边按照权值进行排序,用贪心的思想优先选取权值较小的边,并依次连接,若出现环则跳过此边继续搜,直到已经使用的边的数量比总点数少一即可。

具体算法流程图解如下:

优化:

但是!由于该题数据比较大,我们应该做一些优化

例如Kruskal可以用并查集优化一下

Prim解题代码:

#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#define R register int
using namespace std;int k,n,m,cnt,sum,ai,bi,ci,head[5005],dis[5005],vis[5005];struct Edge
{int v,w,next;
}e[400005];void add(int u,int v,int w)
{e[++k].v=v;e[k].w=w;e[k].next=head[u];head[u]=k;
}typedef pair <int,int> pii;
priority_queue <pii,vector<pii>,greater<pii> > q;void prim()
{dis[1]=0;q.push(make_pair(0,1));while(!q.empty()&&cnt<n){int d=q.top().first,u=q.top().second;q.pop();if(vis[u]) continue;cnt++;sum+=d;vis[u]=1;for(R i=head[u];i!=-1;i=e[i].next)if(e[i].w<dis[e[i].v])dis[e[i].v]=e[i].w,q.push(make_pair(dis[e[i].v],e[i].v));}
}int main()
{memset(dis,127,sizeof(dis));memset(head,-1,sizeof(head));scanf("%d%d",&n,&m);for(R i=1;i<=m;i++){scanf("%d%d%d",&ai,&bi,&ci);add(ai,bi,ci);add(bi,ai,ci);}prim();if (cnt==n)printf("%d",sum);else printf("orz");
}

Kruskal解题代码:

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define MAX_N 5000+5
#define MAX_M 200000+5
struct edge{int u,v;int w;
}E[MAX_M];
int f[MAX_N];
int n,m;
bool cmp(edge a,edge b){return a.w < b.w;
}
void init(){for(int i=1;i<=n;i++) f[i] = i;
}
int find(int x){if(f[x] == x) return x;return f[x] = find(f[x]);
}
void merge(int x,int y){f[find(x)] = find(y);
}
int Kruskal(){int ans = 0, cnt = 0;init();sort(E+1,E+1+m,cmp);for(int i = 1;i<=m;i++){if(cnt == n-1) break;if(find(E[i].u) != find(E[i].v)){merge(E[i].u,E[i].v);ans += E[i].w;cnt++;}}if(cnt != n-1) return 0;return ans;
}
int main(){scanf("%d%d",&n,&m);for(int i = 1;i<=m;i++)scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].w);int ans = Kruskal();if(ans) printf("%d",ans);else printf("orz");return 0;
}

用Prim和Kruskal两种算法,求解最小生成树相关推荐

  1. hdu 1233 还是畅通工程(最小生成树的Prim和Kruskal两种算法的c++实现)(prim算法详解)...

    赤裸裸滴最小生成树(MST),刚学的玩意,用两种方法熟练一下.(都是greedy) Kruskal方法:先对边按照代价非递减排序,再不断添加边且不产生环路,当边数=点数-1结束.判断加入(v,w)是否 ...

  2. 常用十大算法 非递归二分查找、分治法、动态规划、贪心算法、回溯算法(骑士周游为例)、KMP、最小生成树算法:Prim、Kruskal、最短路径算法:Dijkstra、Floyd。

    十大算法 学完数据结构该学什么?当然是来巩固算法,下面介绍了十中比较常用的算法,希望能帮到大家. 包括:非递归二分查找.分治法.动态规划.贪心算法.回溯算法(骑士周游为例).KMP.最小生成树算法:P ...

  3. c语言 最大公约数 最小公倍数的编程,C语言三种算法求解最大公约数与最小公倍数...

    C语言三种算法求解最大公约数与最小公倍数 最大公约数与最小公倍数的求解是很多初学C的人所面临的一道问题.当然这道问题并不难解答,也有很多人已经写过相关的博客,我在此书写此篇博客,一是为了让自己能够夯实 ...

  4. 深度优先搜索(DFS)和广度优先搜索(BFS)两种算法c++

    1.BFS和DFS介绍 深度优先搜索(DFS)和广度优先搜索(BFS)是一种用于遍历或搜索树图的一种算法,在这个过程中保证图或数的每个结点被访问且仅被访问一次,再按照每个结点访问的顺序不同分为深搜和广 ...

  5. 带你辨析最小生成树的两种算法

    最小生成树的算法通常由在几个城市中间修筑路径使其连通并且花费最小引出.如下图所示引例. 多数求最小生成树算法都应用了简称为MST的性质:假设N=(V,{E})是一个连通网,U是顶点V的一个非空子集.若 ...

  6. 三种算法求解经典N皇后问题

    三种算法求解经典N皇后问题 [问题描述] 八皇后问题是一个古老而著名的问题,是回溯算法的典型例题.该问题是十九世纪著名的数学家高斯1850年提出:在8X8格的国际象棋上摆放八个皇后,使其不能互相攻击, ...

  7. 图——最短路径的两种算法

    最短路径 在生活中,例如,当我们坐公交或轻轨时,都会看一下交通图,找到在哪个站下是最快能达到目的地的,也就是路径最小.考虑到交通图的有向性,例如汽车的上山下山.轮船的顺水逆水,所花费的时间或代价就不相 ...

  8. 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)

    图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) 阅读本文前,请确保你已经掌握了递归.栈和队列的基本知识,如想掌握搜索的代码实现,请确保你能够用代码实现栈和队列的基本操作. 深度优先遍 ...

  9. 非负矩阵分解算法C语言,非负矩阵分解的两种算法

    摘要: 随着计算机和信息技术的发展,矩阵分解成为处理大规模数据的一种有效手段.例如,在数值计算中,利用矩阵分解可将规模较大的复杂问题转化为小规模的简单子问题来求解;在应用统计领域,通过矩阵分解得到原数 ...

最新文章

  1. 使用python函数计算3.5四舍五入的结果_python 数字的四舍五入-Go语言中文社区
  2. python网站设计开题报告_XX网站设计开题报告范文
  3. 图片宽度自适应浏览器宽度
  4. WebView完全解读
  5. 简单免杀绕过和利用上线的 GoCS
  6. 【AI初识境】给深度学习新手开始项目时的10条建议
  7. setq 常驻内存lisp_常见Lisp中的set,setq和setf之间的区别?
  8. Ubuntu18.04.4 环境下对属性加密算法CP-ABE环境搭建
  9. 志翔科技用大数据技术为行业云构建“安全之翼”...
  10. LeetCode 题 - 20. 有效的括号
  11. 页面中php传值后循环列表js获取点击的id
  12. 问题 G: Search Problem (IV)
  13. The partial sum problem
  14. AngularJS------Error: Cannot find module '@angular-devkit/core'
  15. ecshop mysql 标题表_ECSHOP商城全站自定义TITLE标题设置
  16. Android实现TTS文字转语音功能
  17. UVa10158 War(并查集)
  18. 拼团小程序源码_微信小程序拼团系统为什么很多商家开发
  19. Ubuntu部署轻量化工具supervisor
  20. 莱昂纳多或出演乔布斯传记电影

热门文章

  1. 双向链表的C++类模板实现
  2. 操作 Wave 文件(13): waveOutGetVolume、waveOutSetVolume
  3. iframe框架及优缺点
  4. sql累计求和时间太长_(七)SQL知识点--窗口函数
  5. python写我爱你_12个精选Python教程我的初恋故事。
  6. 智慧社区互动教室_利用研究与社区互动
  7. (45)npm全局安装包的位置
  8. jQuery 版本viewer.js插件的结构分析与学习
  9. 视觉SLAM笔记(63) RGB-D 稠密建图
  10. 深度学习笔记(12) Batch归一化网络