1596.最少修建多长的公路能把所有村庄连起来(一)

时限:1000ms 内存限制:10000K  总时限:3000ms

描述

一个地区有n个村庄,有一些村子之间可以修路,已知每条路的长度,问最少修建多长的公路可以把所有的村子连接起来。

输入

先输入两个正整数n,m(n小于10000,m小于100000),表示有n个村庄,m条可以修建的路,接下来的m行每行三个整数,前两个表示村庄的编号(0~n-1),第三个表示这条路的长度。

输出

输出路的总长度的最小值。


#include <iostream>
#include <climits>using namespace std;//本题选用Kruskal算法,因邻接矩阵顶点太多,边太少
//若用二维数组存放数据太浪费
//本题采用并查集判断两个顶点是否连通int n,m;int a[10000];    //并查集
int x[100000],y[100000],dis[100000];    //存放边
int isIn[100000];   //边是否已在集合中int fsearch(int x);         //返回并查集中x节点的根节点
void a_add(int x, int y);   //将两个顶点连通
bool isUn(int x, int y);    //判断x和y两个顶点是否连通int main()
{//Krustal算法+并查集//输入数据cin>>n>>m;for(int i=0; i<m; i++){cin>>x[i]>>y[i]>>dis[i];}//初始化for(int i=0; i<n; i++){a[i]=i;}//将边按权值升序排列for(int i=0; i<m; i++){for(int j=i; j<m; j++){if(dis[j]<dis[i]){swap(dis[j],dis[i]);swap(y[j],y[i]);swap(x[j],x[i]);}}}//按升序遍历边,加入集合,共m条边int dist=0;for(int i=0; i<m; i++){if(!isUn(x[i],y[i]))//若第i条边的两个顶点不连通{a_add(x[i],y[i]);   //将两个顶点连通dist+=dis[i];   //加入这条边的边长}else                //若已经连通则查看下一条边{continue;}}cout<<dist<<endl;return 0;
}int fsearch(int x)   //返回并查集中x节点的根节点
{int f=a[x];while(f!=a[f]){f=a[f];}a[x]=f;return f;
}void a_add(int x, int y)    //将两个顶点连通
{int kx=fsearch(x);int ky=fsearch(y);a[ky]=kx;
}bool isUn(int x, int y)     //判断x和y两个顶点是否连通
{int kx=fsearch(x);int ky=fsearch(y);if(kx==ky){return true;}else{return false;}
}

1597.最少修建多长的公路能把所有村庄连起来(二)

时限:1000ms 内存限制:10000K  总时限:3000ms

描述

一个地区有n个村庄,有一些村子之间可以修路,已知每条路的长度,问最少修建多长的公路可以把所有的村子连接起来。

输入

先输入一个正整数n(n小于500),表示有n个村庄,接下来n行每行n个正整数,其中第i行第j列的元素表示第i个村庄到第j个村庄之间的距离。

输出

输出路的总长度的最小值。


#include <iostream>
#include <climits>using namespace std;//本题选用Prim算法,因邻接矩阵不稀疏int n,m;int dist[500][500]; //邻接矩阵
int isIn[10000];    //节点是否在集合中
int f[10000];       //权值:每个节点到集合的距离int mindist();   //返回当前离集合最近点的下标int main()
{//Prim算法cin>>n;for(int i=0; i<n; i++)  //输入数据{for(int j=0; j<n; j++){cin>>dist[i][j];}}//初始化isIn数组isIn[0]=1;  //将节点0加入集合for(int i=1; i<n; i++){isIn[i]=0;}//初始化各节点权值for(int i=1; i<n; i++){f[i]=dist[0][i];    //初始权值为到顶点i的距离}int dis=0;  //总距离for(int cnt=1; cnt<n; cnt++)    //每次for循环添加一个节点进集合{int x=mindist();   //返回离集合最近节点下标//cout<<x<<' '<<isIn[x]<<endl;isIn[x]=1;  //将该节点加入集合dis+=f[x];  //将权值加入总距离中//cout<<dis<<' ';for(int i=0; i<n; i++)  //更新各节点权值{if(!isIn[i])    //遍历不在集合中的节点{if(dist[x][i]<f[i]){f[i]=dist[x][i];//cout<<f[i]<<endl;}}}}cout<<dis<<endl;return 0;
}int mindist()    //返回当前离集合最近点的下标
{int min_i=1;int min_dist=INT_MAX;for(int i=1; i<n; i++){if(!isIn[i]){if(f[i]<min_dist){min_dist=f[i];min_i=i;}}}return min_i;
}

【后记】

1.最小生成树问题,有两种算法,Prim算法与Krustal算法

当e=Ω(n²)时,Prim算法性能好

当e=o(n²)时,Krustal性能好

2.Prim算法将顶点分为两个集合A和B,集合A中最初只有顶点0,其余顶点都在集合B中

集合B中每个顶点都有一个权值 f,f [ i ] 定义为“顶点 i 到集合A的最短距离”,初始值为“顶点 i 到顶点0的最短距离”

若顶点 i 到顶点0没有连接边,那么 f [ i ] 的初始值为INT_MAX,即无穷大,需要#include <climits>

开始for循环,每次循环,从集合B中选取一个权值最小的顶点X加入集合A,相当于顶点X已经与集合A中的各顶点连通,然后更新集合B中剩下的顶点权值

更新意义在于:顶点X已经从集合B加入了集合A,那么如果集合B中有一个顶点Y到顶点X的距离比它到集合A的距离更短,就要把顶点Y的权值更新成它到顶点X的距离

当for循环次数等于顶点数-1时,每个顶点都被加入了集合A,意味着所有顶点都连通起来

Prim算法演示图(红色数字权值是每张图中加入新顶点前还没更新的权值)

3.Kruskal算法,先将各条边按照距离值从小到大排列

开始for循环,每次循环选取一条距离值最小的边,判断一下这条边两端的顶点A和顶点B是否连通

如果A和B不连通,就把它们连通起来,确定添加这条边

如果A和B连通,就删除这条边不添加(否则会形成回路),查看下一条边

当循环次数等于边数时,所有边都被查看了一遍,要么添加要么删除,最后所有顶点都连通起来,并且没有回路

Kruskal算法演示图

4.在Kruskal算法中,需要判断一条边的两个顶点是否连通,这里用到了并查集

并查集可以用一个数组a[]表示,a [ i ] = i 表示节点 i 为根节点

若一条边的顶点A和顶点B的根节点相同,说明两个顶点在一棵树上,即连通

若顶点A和顶点B的根节点不同,说明不连通,那么在Kruskal算法中需要让A和B连通,此时只需求A的根节点root(A),B的根节点root(B),令a[ root(A) ] = root(B)就可以,具体代码如下:


for(int i=0; i<n; i++)    //初始化并查集
{a[i]=i;    //每个节点都是自己的根节点
}int fsearch(int x)   //返回并查集中x节点的根节点
{int f=a[x];while(f!=a[f])    //只有a[f]==f时,f才是根节点{f=a[f];}a[x]=f;    //更新x的根节点,让其直接指向freturn f;
}void a_add(int x, int y)    //将两个顶点连通
{int kx=fsearch(x);    //x的根节点int ky=fsearch(y);    //y的根节点a[ky]=kx;    //让ky的根节点变成kx
}

【NOJ1596、1597】【贪心算法之最小生成树】最少修建多长的公路能把所有村庄连起来(图示Prim与Kruskal算法)相关推荐

  1. 最小生成树(Prim、Kruskal)算法,秒懂!

    前言 在数据结构与算法的图论中,(生成)最小生成树算法是一种常用并且和生活贴切比较近的一种算法.但是可能很多人对概念不是很清楚,什么是最小生成树? 一个有 n 个结点的连通图的生成树是原图的极小连通子 ...

  2. dijkstra算法_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法

    讲在前面的话,图的算法太多,理论知识肯定一篇文章讲不完,关于理论知识大家可以参考教材Sedgewick的<算法>或reference的链接,本文主要还是想在一篇文章中记录六种算法的Pyth ...

  3. dfs时间复杂度_Python实现图的经典DFS、BFS、Dijkstra、Floyd、Prim、Kruskal算法

    讲在前面的话,图的算法太多,理论知识肯定一篇文章讲不完,关于理论知识大家可以参考教材Sedgewick的<算法>或reference的链接,本文主要还是想在一篇文章中记录六种算法的Pyth ...

  4. Prim和Kruskal算法应用----城市水管连接

    Prim和Kruskal算法应用----城市水管连接 问题描述: Description: 现在有n个城镇,编号为1, 2, 3, 4-n.他们之间有m条互通的道路,每条道路有相应的长度,现在基于这些 ...

  5. 【图解】Prim和Kruskal算法的区别

    [贪心]Prim和Kruskal算法的区别 Kruskal算法和Prim算法的优劣 Kruskal算法,相较于Prim算法是基于点的操作,Kruskal算法是基于边的操作,思想也比Prim简单,更容易 ...

  6. 数据结构(六):图的概念、存储方式、基本操作、最小生成树、最短路径、有向无环图、关键路径 | Prim、Kruskal算法 | BFS、Dijkstra、Floyd算法 | 拓扑排序 | 求关键路径

    文章目录 第六章 图 一.图 (一)图的定义 (二)图逻辑结构的应用 (三)无向图.有向图 (四)简单图.多重图 (五)顶点的度.入度.出度 (六)顶点-顶点的关系描述 (七)连通图.强连通图 (八) ...

  7. Prim和Kruskal算法

    1. Prim算法 1.1 概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex ...

  8. 浙大数据结构:08-图7 公路村村通 (30 分)Prim与Kruskal算法

    08-图7 公路村村通 (30 分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N( ...

  9. 数据结构与算法—最小生成树(Prim算法和Kruskal算法算法详解)

    前言 在数据结构与算法的图论中,(生成)最小生成树算法是一种常用并且和生活贴切比较近的一种算法.但是可能很多人对概念不是很清楚.我们看下百度百科对于最小生成树定义: 一个有 n 个结点的连通图的生成树 ...

最新文章

  1. ASP保存远程图片到本地 同时取得第一张图片
  2. 华硕服务器芯片,全球首款875P芯片组双至强服务器主板华硕PC-DL震撼上市
  3. 你这种直来直去的英语,买家受不了
  4. 网站数据分析:基于用户细分的比较分析
  5. 关于MySQL查询优化 の 30条忠告
  6. java二叉树插入节点_[javaSE] 数据结构(二叉查找树-插入节点)
  7. dev c++怎么设置断点_Linux怎么挂载移动硬盘光盘U盘之案例分享
  8. 构建富互联网应用程序监控工作流和流程(4)
  9. Verilog设计分频器(面试必看)
  10. EMLOG复制网站文字提醒弹窗源码美化版
  11. 一点一点看JDK源码(二)java.util.List
  12. extjs mysql_ExtJS与PHP、MySQL实现存储
  13. 长话无需短说 讯飞输入法超长语音输入不限时
  14. Java 图书管理系统
  15. 飞桨2.0高层api教程——使用BERT实现自动写诗
  16. 《天才在左、疯子在右》随笔
  17. 数字逻辑课上如何制作FPGA游戏?
  18. 大数据埋点那些事儿,手机 APP 是不是在偷听我说话?
  19. MATLAB-ezplot绘图函数
  20. Android番外篇 “adb”不是内部或外部命令,也不是可运行的程序或批处理文件

热门文章

  1. 如何将其他音频格式转换成WAV格式?我来教你几招
  2. 项目将com.thoughtworks.xstream升级到1.4.18遇到的问题:com.thoughtworks.xstream.security.ForbiddenClassException
  3. C# 如何将PDF转为多种图像文件格式(Png/Bmp/Emf/Tiff)
  4. python--文件的相关操作
  5. PKCS#1、PKCS#5、PKCS#7、PKCS#8到底是什么?
  6. 通过VNC远程接入BeagleBone Black桌面
  7. 2014中山大学考研计算机学院复试线及调剂,2014年中山大学信息科学与技术学院考研复试线...
  8. [SAP]RFC函数的JCo Java调用代码模板
  9. java的socket包_Java socket详解(转)
  10. 哈工大计算机系统大作业-程序人生-Hello’s P2P