一学就废的并查集它来了

文章目录

  • 题目描述
  • 输入
  • 输出
  • 样例输入
  • 样例输出
  • 提示
  • 算法思想
  • 代码实现
    • 寻找根节点
    • 汇总连接情况
    • 完整代码
      • 关于flag的初值

题目描述

某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?


输入

测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。


输出

对每个测试用例,在1行里输出最少还需要建设的道路数目。


样例输入

4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0


样例输出

1
0
2
998


提示

Huge input scanf is recommended.


算法思想

数组下标作为一个点,数组中存储的元素作为其连接的另一个点,全联通即:将所有下标对应的点归拢到一个点上(也就是除了根节点,大家对应的都不是自己啦),相当于大家都跟一个点连接的话,当然是全联通状态啦。


代码实现


寻找根节点

定义一个函数用来搜索给出结点的根节点,最终返回根节点的值(康康大家是不是来自同一地方嘛)

int find(int x){while(data[x]!=x){x=data[x];}return x;//返回根节点的值
}

当联通关系不多,树的深度不深的时候,用上一种方法无疑是很快的,但是如果联通关系错综复杂,树的深度很深,例如每层只有一个节点这种奇葩情况,遍历搜索根节点就会很费时间,这时候就要用到“路径压缩“这一方法,即将所查询节点的数组内容由”父节点“改为”祖宗节点“。

int find(int x){//寻找根节点int ans,tmp;ans = x;while(data[x]!=x){//x是根节点x=data[x];}while (ans != x) {//路径压缩tmp = data[ans];data[ans] = x;//数组内容直接储存根节点,不再存储父节点ans = tmp;//接下来压缩父节点}return x;//返回根节点的值
}

汇总连接情况

将所给的两个点的连接情况进行记录,根节点不一样的话说明是第一次告知两个节点联通,所以要把根节点改成一样的, 一样的话当然就是告知过了,不需要改变(大型认祖归宗活动,哦兄弟我们是一家的,来来来族谱上记一下/哦兄弟我们是一家的,来来来……桥豆麻袋!族谱上记过了……不用记了诶)淦!你忘了我们很久以前见过面的!!!
⬆(淦!你忘了我们很久以前见过面的!!!)

void add(int x, int y){if(find(x)!=find(y)){data[find(x)]=find(y);}
}

完整代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;int data[1003];int find(int x){//寻找根节点while(data[x]!=x){x=data[x];}return x;//返回根节点的值
}void add(int x, int y){if(find(x)!=find(y)){data[find(x)]=find(y);}
}int main(int argc, char const *argv[]) {int n,m;//n元素个数,m元素连接条数int x,y;//x,y是两个相连的元素int flag;//未联通的结点数while (cin >> n,n) {memset(data,0,sizeof (data));for (int i = 1; i <= n; i++) {data[i] = i;}for (cin >> m; m > 0; m--) {cin >> x;cin >> y;add(x,y);}flag = -1;for (int i = 1; i <= n; i++) {if(data[i]==i){flag++;//数组内容等于数组下标表示和自己联通}}cout << flag << endl;}return 0;
}

关于flag的初值

其实难以理解的地方可能是flag的初值为什么要设置成-1,flag存储的是数组内容等于数组下标的情况(自己连接自己的情况)有多少,每有一个就说明有一种连接种类,全联通状态只有一个这样的情况——即根节点,也就是除了根节点和自己连接,其他的节点都不和自己连接,所以要把根节点这个情况排除在外,即flag初值为-1。
这样一来,当全联通时,只有根节点的data[i]=i,flag++,flag的值就为0,最后输出flag的值也就是还需要修多少条路。

举个栗子可能更方便理解
当输入为
5 2
1 2
4 5

此时data数组的情况是(第四行):在这里插入图片描述
连接种类有三种:根节点为2的1、2连接、根节点为3的自己和自己连接、以及根节点为5的4、5连接。
此时data[i]=i的情况会出现3次,flag的终值也就是-1自加三次,也就是2,表示还需要修两条路,举个例子,3 2,3 4这样修,那会出现什么情况呢?(为了便于理解拆分一下这个过程)
在这里插入图片描述
在这里插入图片描述
3 2的时候,3将2的根节点(也就是2本身)认作祖宗,3 4的时候,经过find函数查看族谱,诶大家祖宗不一样诶但我们是一家人,那就一个祖宗认另一个祖宗为爹好了,这样大家就在一起了,于是经过add函数修改族谱,3他爹2就认4他爹5当爹,1和3就成了5的乖孙孙。大家就是一家人了mua。(谁认谁当祖宗就看你怎么写了哦吼,data[find(x)]=find(y)是后面的数当前面的数的祖宗,data[find(y)]=find(x)就是前面的当祖宗咯)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/443898.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

百战c++(2)

delete 和 delete []的真正区别 delete 对应 new delete[]对应new[]对于简单类型包括简单类型数组&#xff0c;delete 与delete[]没有区别。对于自定义类型数组&#xff0c;delete 只会删除一个元素&#xff0c;delete 则会删除所有元素。 指针和数组的区别 野指针是什么 野指…

Linux实验一:常用的Linux命令

文章目录一、实验目的二、实验要求三、实验内容1、系统的使用2、命令的使用3、文件操作4、系统询问与权限口令5、其它常用命令四、实验操作1、基本命令的使用2、文件和目录操作3、创建用户帐户一、实验目的 1、熟悉Linux的桌面环境&#xff1b; 2、了解Linux所安装的软件包 3、…

Linux实验二:vi编辑器的使用

文章目录一、实验目的二、实验要求三、实验内容1、创建文件2、编辑文件一、实验目的 1、练习并掌握Linux提供的vi编辑器来编译C程序 2、学会利用gcc、gdb编译、调试C程序 3、本次实验的目的是让同学们了解如何使用vi编辑器进行创建和编辑文件 二、实验要求 1、文件编辑器vi…

百战c++(os1)

Linux中的锁 互斥锁&#xff1a;mutex&#xff0c;用于保证在任何时刻&#xff0c;都只能有一个线程访问该对象。当获取锁操作失败时&#xff0c;线程会进入睡眠&#xff0c;等待锁释放时被唤醒 读写锁&#xff1a;rwlock&#xff0c;分为读锁和写锁。处于读操作时&#xff0…

Linux实验三:Shell编程

文章目录一、实验目的二、实验要求三、实验内容1、通配符的使用2、重定向3、管道4、shell变量5、建立下面的脚本&#xff0c;运行并分析输出结果&#xff0c;并给出代码注释。6、编写脚本一、实验目的 1.为文件扩展名使用通配符 2.标准输入、标准输出和标准错误的重定向 3.使…

Linux实验四:编译和调试工具的使用

文章目录一、实验目的&#xff1a;二、实验要求三、实验内容四、实验操作1、用gcc编译程序&#xff0c;写出编译过程&#xff0c;并给出运行结果。2、调试程序&#xff0c;要求用gdb进行调试并给出修改方案。3、make的使用一、实验目的&#xff1a; 1、练习并掌握Linux提供的v…

Linux实验五:Linux环境下的C语言编程

文章目录一、实验目的&#xff1a;二、实验要求三、实验内容1、编写一段C语言程序使其完成&#xff1a;父进程创建两个子进程&#xff0c;每个进程都在屏幕上显示自己的进程ID号。2、上机调试下面的程序&#xff0c;观察运行结果&#xff0c;分析原因。3、利用两个管道进行双向…

ndarray对象的建立

文章目录ndarray&#xff08;别名array&#xff09;常用属性创建NumPy数组使用array()函数使用zeros()函数使用ones()函数使用empty()函数使用arange()函数注意ndarray&#xff08;别名array&#xff09; 常用属性 import numpy as np # Numpy工具包data np.arange(12).res…

Numpy数组的广播机制

文章目录前言数组广播广播机制的使用条件前言 Numpy数组不需要循环遍历&#xff0c;即可对每个元素执行批量的算术运算操作&#xff08;矢量化运算&#xff09;。当两个数组大小&#xff08;Numpy.shape&#xff09;不同时&#xff0c;进行算术运算会出现广播机制。 数组广播…

数组的转置和轴对称

文章目录T属性transpose()方法swapaxes()方法T属性 import numpy as np # Numpy工具包data np.arange(12).reshape(3, 4) # 创建一个3行4列的数组 print(data)# 数组的转置和轴对称 data1 data.T print(data1)print(data) [[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] print(dat…

管道实现父子进程的信息传递(一)【fork函数、pipe函数、write/read操作、wait函数】

文章目录题目描述代码实现关于pipe函数关于读写操作关于读写端口关于wait函数功能&#xff1a;注意&#xff1a;关于fork函数题目描述 编写一个程序&#xff0c;利用管道实现父子进程的通信&#xff0c;父进程向子进程发送信息&#xff0c;由子进程输出显示。 代码实现 #inclu…

基础的shell编程问题(一)

文章目录题目一题目描述代码实现关于$#的有关内容实测本程序的作用题目二题目描述代码实现注释关于argc、argv关于read函数关于文件描述符关于write函数本程序的作用题目三题目描述代码实现实测关于grep命令关于read命令题目四题目描述代码实现关于test命令实测题目一 题目描述…

基础的shell编程问题(二)

文章目录题目一题目描述代码实现结果验证关于本题题目二题目描述代码实现结果测试题目三题目描述代码实现及结果测试题目四题目描述代码实现及结果测试题目五题目描述代码实现及结果测试题目一 题目描述 输入的命令行参数必须是hello&#xff0c;才会正确显示&#xff1b;否则…

Numpy实现酒鬼漫步问题【以及randint()、where()、cumsum()、argmax()的用法详解】

文章目录题目描述代码实现关于本题涉及到的几个函数randint()where()cumsum()题目拓展题目描述代码实现题目拓展题目描述代码实现argmax()题目描述 从前有一个酒鬼&#xff0c;喝醉了行走在一条直线上&#xff0c;每走一步方向是不确定的&#xff08;向前或者向后&#xff09;…

搞清axis的含义,这一篇就够了!

文章目录axis的含义旁门左道式理解二维数组中的axis三维数组中的axis正规理解axis的含义 在自己分析之前先摆上官方关于多维数组中axis的值的定义&#xff1a; axis 0&#xff0c;表示第一个维度 axis 1&#xff0c;表示第二个维度 axis -1&#xff0c;表示最后一个维度…

Struts2.3.5+Hibernate3+Spring3.1基于注解实现的多文件上传,下载

Struts2.3.5Hibernate3Spring3.1基于注解实现的的多文件上传&#xff0c;下载,这里是上传文件到数据库中&#xff0c;上传控件可以增加和删除&#xff0c;有需要的朋友可以看看。 以下是源码下载地址&#xff1a;http://www.zuidaima.com/share/1639672872438784.htm jar包的下…

【精品计划1】动态规划入门到熟悉,看不懂来打我啊

持续更新。。。。。。 2.1斐波那契系列问题 2.2矩阵系列问题 2.3跳跃系列问题 3.1 01背包 3.2 完全背包 3.3多重背包 3.4 一些变形选讲 2.1斐波那契系列问题 在数学上&#xff0c;斐波纳契数列以如下被以递归的方法定义&#xff1a;F(0)0&#xff0c;F(1)1, F(n)F(n-1)…

【大总结2】大学两年,写了这篇几十万字的干货总结

本文是我大学两年知识的总结。涵盖数据结构、算法、语言基础、操作系统、关系数据库、NOSQL、网络/前端/项目基础知识、安全和测试、框架的学习、中间件和工具、设计模式和框架原理、我推荐的资料、我的建议 本篇文章应该算是Java后端开发技术栈的&#xff0c;但是大部分是基础…

《这是全网最硬核redis总结,谁赞成,谁反对?》六万字大合集

我摊牌了&#xff0c;这篇文章&#xff0c;值得99%的人收藏 此文后续会改为粉丝可见&#xff0c;所以喜欢的请提前关注和收藏&#xff0c;不迷路。 最近有五本我喜欢的redis实体新书&#xff0c;想要的去评论&#xff0c;我写个随机数抽奖包邮送给你。 那么&#xff0c;准备好…

Python数据预处理之异常值的处理——【自定义的three_sigma()函数、boxplot()方法】

文章目录基于3σ原则检测异常值代码实现测试基于箱型图检测异常值异常值的处理基于3σ原则检测异常值 3σ原则&#xff0c;又称拉依达准则。是指假设一组检测数据只含有随机误差。对其进行计算处理得到标准偏差&#xff0c;按一定概率确定一个区间&#xff0c;凡是超过这个区间…