首页 > 其他分享 >并查集入门1【L2】

并查集入门1【L2】

时间:2024-02-01 09:35:06浏览次数:27  
标签:连通 入门 int 复杂度 查集 --- 棋子 L2 find

讲义

 

引例1

•有N个计算机中心,开始时都是独立的。后来不断的架设了M条网线,每条网线把其中的2个计算机中心连接起来。

•直接或间接连接的计算机中心都可以相互通信,组成一个网络。 

•问有多少个连通网络?

image.png

 

 

引例2

•围棋的棋子有黑色和白色两种,相同颜色的棋子如果是上下或左右相邻的,则称这两个棋子是连通的,直接或间接连通的棋子称为一块棋。 

•现在,不断给出N个落棋子的信息(颜色、横坐标、纵坐标),问棋盘上有多少块棋?

image.png

 

 

 

建立数学模型

•计算机中心、棋子  ---   点 

•网线、相邻  --- 两点关系  --- 边 

•网络、块  --- 连通块

 

image.png

 

 

查找操作(Find)

 

•检查:两个点是否在一个连通快

 

 

 

1.png

 

 

 

合并操作(Union)

 

•合并:添加一条连线

 

 

 

image.png

 

 

方法名称:并查集(Union-Find Set)

•合并 --- Union 

•检查 --- Find 

•点集 --- Set

 

 

“暴力”算法

 

•一个连通块的点用相同的id表示 

 

•检查:只要看两个点的id是否相同!

 

image.png

 

•合并1:加边(3,4),两端点在一个连通块,不用处理。

 

image.png

 

•合并2:加边(5,2),两端点不在一个连通块,怎么办?

 

image.png

 

 

 

“暴力”算法

•合并2:加边(5,2),两端点不在一个连通快 

•(1)改id相同 (2)连通块数-1

1.png

 

2.png

3.png

 

 

“暴力”算法的时间复杂度

•点N个,边M个: 

•合并的时间复杂度:O( min(N,M)*N ) 

•查找的时间复杂度:O(1)

 

 

 

 

 

新方法

image.png

 

树结构

•Tree:根在上的树 

•Father:有向边

image.png

 

 

特点:

•根“没有”有向边

•其他节点有一条有向边指向“父节点”

 

统一格式:

• 根的有向边指向自己  

image.png

 

•检查操作:
  两个点有相同的根就是在一个连通块

 

•合并操作(6,3)

image.png

 

 (这里图片可能有误)

 

 

•查:找点x的所在“树”的根函数

1.png

 

从x出发,按照fa[x]向上一直找到根

 

•并:添加关系(a,b)时合并函数:

2.png

 

 

 

查找根的时间复杂度问题

•find_root()函数,坏的情况,向上很多层。

image.png

“压缩路径”技术---扁平化。

image.png

有压缩路径功能的查找函数

image.png

 

用递归写的函数

image.png

 

image.png

并查集算法时间复杂度

 

一次查找根find_root()的平均复杂度:

    O(5)

一次合并union(a,b)的平均复杂度:

    O(5)

算法的总复杂度:

   O(M*5+N)

 

 

练习


第1题     网络2 查看测评数据信息

有N个计算机中心(编号为1,2,3,…,N),开始时都是独立的。后来不断的架设了M条网线,每条网线把其中的2个计算机中心连接起来。直接或间接链接的计算机中心都可以相互通信,组成一个网络。问有多少个网络?


输入格式

第1行:两个整数N、M,N范围[1,100000] ,M范围[1,500000]。

下面M行:每行2个整数,表示网线连接的计算机中心编号。


输出格式

一个整数,表示有多少个不连通的网络。


输入/输出例子1

输入:

5 4

1 5

2 3

2 4

3 4


输出:

2

样例解释



#include <bits/stdc++.h>
using namespace std;

const int N=100005;
int n, m, u1, v1, ans=0, f[N];
int find(int x)
{
	if (f[x]==x) return x; //因为根的根是自己,所以如果x=根[x],证明找到根
	return f[x]=find(f[x]); //压缩路径,找到根后,把x的根=最终联通块的根
}
int main()
{
//网络,边输入边判联通性 scanf("%d%d", &n, &m); for (int i=1; i<=n; i++) f[i]=i; //刚开始假设根是自己 ans=n; //假设刚开始联通块为n for (int i=1; i<=m; i++) { scanf("%d%d", &u1, &v1);
//等于join函数 int roota=find(u1); //分别找根 int rootb=find(v1); if (roota!=rootb) //不属于同一个根,不联通 f[roota]=rootb, ans--; //联通块--,但是两块相连
//join结尾 } printf("%d", ans); return 0; }

 


第2题     围棋1 查看测评数据信息

围棋的棋子有黑色和白色两种,相同颜色的棋子如果是上下或左右相邻的,则称这两个棋子是连通的,直接或间接连通的同色棋子称为一块棋。

现在,给出N个落棋子的信息(颜色、横坐标、纵坐标),问棋盘上有多少块棋?

 



输入格式

第一行一个正整数N,范围[1,300]。

下面N行,每行3个正整数c,x,y表示一个棋子的颜色、横坐标、纵坐标。c=1为黑色,c=2为白色;x,y的范围[1,19]


输出格式

一个正整数,表示棋盘上有多少块棋。


输入/输出例子1

输入:

6

1 3 3

2 2 2

1 3 2

2 1 2

1 2 3

2 1 1


输出:

2

样例解释

小技巧:x*max(n, m)+y,所得每个数都不会一样(这个公式只会得出一个固定的数),所以可以利用这个来算方格(x,y)坐标转换成一个数的情况,方便找

#include <bits/stdc++.h>
using namespace std;

const int N=22;
int n, c, x, y, f[N*N], mp[N][N], ans=0;
int dx[]={-1, 0, 0, 1}, dy[]={0, -1, 1, 0};
int find_root(int x) //找根节点
{
	if (f[x]==x) return x;
	return f[x]=find_root(f[x]);
}
void join(int a, int b) //连边
{
	int roota=find_root(a);
	int rootb=find_root(b);
	if (roota!=rootb)
	{
		f[rootb]=roota;
		ans--;
	}
}
int main()
{
//围棋,把棋子向四边扩散,边输入边扩散,看看连不连通即可(联通就ans--,并连边) scanf("%d", &n); for (int i=0; i<=19*19; i++) f[i]=i; //刚开始假设根是自己 ans=n; //刚开始假设全部联通 for (int i=1; i<=n; i++) { scanf("%d%d%d", &c, &x, &y); mp[x][y]=c; for (int j=0; j<4; j++) { int nx=x+dx[j], ny=y+dy[j]; if (nx>=1 && nx<=19 && ny>=1 && ny<=19) if (mp[nx][ny]==c) //颜色相同 join(x*19+y, nx*19+ny); //小技巧,连边 } } printf("%d", ans); return 0; }

 

标签:连通,入门,int,复杂度,查集,---,棋子,L2,find
From: https://www.cnblogs.com/didiao233/p/18000532

相关文章

  • [office] excel2010工作表的切换与重命名
    在使用excel工作表时,我们可能会对多个工作表进行来回切换查看,今天小编为大家介绍一下如何切换工作表及重命名工作表。一、切换工作表切换工作表主要有两种方法:1、直接使用鼠标对工作表标签sheet进行点击切换;2、使用快捷键,ctrl+pageup和ctrl+pagedown键,可以快速进行工作表切换。二......
  • python网络编程笔记(一)Socket 编程入门
    一:Socket简介套接字起源于20世纪70年代加利福尼亚大学伯克利分校版本的Unix,即人们所说的BSDUnix。因此,有时人们也把套接字称为“伯克利套接字"或"BSD套接字”。一开始,套接字被设计用在同-台主机上多个应用程序之间的通讯BSDSocket接口是TCP/IP网络的API在Linux,Unix和W......
  • 最新Burp Suite入门技术
    BurpSuite的安装BurpSuite是一款集成化的渗透测试工具,包含了很多功能,可以帮助我们高效地完成对Web应用程序的渗透测试和安全检测。BurpSuite由Java语言编写,Java自身的跨平台性使我们能更方便地学习和使用这款软件。不像其他自动化测试工具,BurpSuite需要手动配置一些参数,触发......
  • Vim-从放弃到入门
    初识VimVim被称为神一样的编译器,人类历史上最好文本编辑器(^_^)。学习成本很高,学习路线陡峭。下面列举一些入门的教程:慕课网-玩转Vim从放弃到爱不释手新手必看Vim实用技巧(第2版)精通Vim:用Vim8和Neovim实现高效开发vimtutor,在命令行中输入vimtutor-gzh插件入门,GitHub链接......
  • kettle从入门到精通 第三十七课 kettle 全量同步(数据量小)
    1、下图是一些常见的数据同步业务场景:实时数据:对实时性要求很高,延迟在毫秒范围内。常见的有kafka/rabbitmq等消息中间件,mysqlbinlog日志,oracle归档日志等。离线数据:对实时性要求不高,可以分钟级、小时级、日级等。比如历史数据迁移或者T日处理T-1日数据等。全量同步:一般情况下......
  • Rabbit MQ 入门
    简单案例:消息生产与消费pom.xml配置<dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><!--3.6.5是稳定版本--><version>3.6.5</version></dependency>生产者importcom.rab......
  • Java 编程指南:入门,语法与学习方法
    Java是什么?Java是一种流行的编程语言,诞生于1995年。由Oracle公司拥有,运行在超过30亿台设备上。Java可以用于:移动应用程序(尤其是Android应用)桌面应用程序网络应用程序网络服务器和应用程序服务器游戏数据库连接等等!为什么使用Java?Java拥有以下优势:跨平......
  • CS231N Assignment3 入门笔记(Q4 GANs)
    斯坦福2023年春季CS231N课程第三次作业(最后一次)解析、笔记与代码,作为初学者入门学习。在这项作业中,将实现语言网络,并将其应用于COCO数据集上的图像标题。然后将训练生成对抗网络,生成与训练数据集相似的图像。最后,将学习自我监督学习,自动学习无标签数据集的视觉表示。本作业的......
  • [office] excel2003文件转成pdf文件的方法
    Excel中经常需要转换成PDF文件格式,Excel具体该如何转换成PDF呢?接下来是小编为大家带来的excel2003文件转成pdf文件的方法,供大家参考。excel2003文件转成pdf文件的方法:Excel转换PDF格式步骤1:下载安装pdf虚拟打印机Excel转换PDF格式步骤2:文件】【打印】,打印机选择pd......
  • Qt QCustomPlot 入门教程
    简述QCustomPlot是一个基于QtC++的图形库,用于绘制和数据可视化-制作漂亮的2D图-曲线图、趋势图、坐标图、柱状图等,并为实时可视化应用程序提供高性能服务。它没有进一步的依赖关系,并有着良好的文档记录。QCustomPlot可以导出为各种格式,比如:PDF文件和位图(如:PNG、JPG......