【并查集专题】【蓝桥杯备考训练】:网络分析、奶酪、合并集合、连通块中点的数量、格子游戏【已更新完成】

目录

1、网络分析(第十一届蓝桥杯省赛第一场C++ A组/B组)

2、奶酪(NOIP2017提高组)

3、合并集合(模板)

4、连通块中点的数量(模板)

5、格子游戏(《信息学奥赛一本通》)


1、网络分析(第十一届蓝桥杯省赛第一场C++ A组/B组)

小明正在做一个网络实验。

他设置了 n 台电脑,称为节点,用于收发和存储数据。

初始时,所有节点都是独立的,不存在任何连接。

小明可以通过网线将两个节点连接起来,连接后两个节点就可以互相通信了。

两个节点如果存在网线连接,称为相邻。

小明有时会测试当时的网络,他会在某个节点发送一条信息,信息会发送到每个相邻的节点,之后这些节点又会转发到自己相邻的节点,直到所有直接或间接相邻的节点都收到了信息。

所有发送和接收的节点都会将信息存储下来。

一条信息只存储一次。

给出小明连接和测试的过程,请计算出每个节点存储信息的大小。

输入格式

输入的第一行包含两个整数 n,m,分别表示节点数量和操作数量。

节点从 1 至 n 编号。

接下来 m 行,每行三个整数,表示一个操作。

  • 如果操作为 1 a b,表示将节点 a 和节点 b 通过网线连接起来。当 a = b 时,表示连接了一个自环,对网络没有实质影响。
  • 如果操作为 2 p t,表示在节点 p 上发送一条大小为 t 的信息。
输出格式

输出一行,包含 n 个整数,相邻整数之间用一个空格分割,依次表示进行完上述操作后节点 1 至节点 n 上存储信息的大小。

数据范围

1≤n≤10000
1≤m≤1e5
1≤t≤100

输入样例1:
4 8
1 1 2
2 1 10
2 3 5
1 4 1
2 2 2
1 1 2
1 2 4
2 2 1
输出样例1:
13 13 5 3
思路:

连接的时候创建一个新的根节点,作为祖先(通过创建新节点,可以实现在之后的dfs中不会将之前的信息加到后连接的计算机上

依次执行输入的指令,传达的信息都加到根节点上

dfs,把发送的信息全部累加到根节点上

遍历输出根节点的信息(如果对于节点i,p[i]==i则说明这是个根节点,不然说明这个根节点已经其点的子节点了

代码:
#include<bits/stdc++.h>

using namespace std;

const int N=2e4+10,M=N<<1;

int p[N];

int h[M],e[M],ne[M],idx;

int add(int a,int b)
{
	e[idx]=b;//值存到e里(idx是e的编号) 
	ne[idx]=h[a];//d的编号的下一个指向h【a】指向的编号 
	h[a]=idx++;//h【a】指向b的编号 
}

int f[N];//存储信息 

int n,m;

int find(int x)
{
	if(x!=p[x])p[x]=find(p[x]);
	return p[x];
}

void merge(int a,int b,int &root)
{
	a=find(a);
	b=find(b);
	if(a!=b)
	{
		p[a]=p[b]=root;
		add(root,a);
		add(root,b);
		root++;
	}
}

void dfs(int son,int father)
{
	f[son]+=f[father];
	for(int i=h[son];i!=-1;i=ne[i])
	{
		int j=e[i];
		dfs(j,son);
	}
}

int main()
{
	memset(h,-1,sizeof h);
	cin>>n>>m;
	
	for(int i=1;i<=n*2;i++)
	{
		p[i]=i;
	}
	 
	int root=n+1; 
	
	while(m--)
	{
		
		int t,a,b;
		cin>>t;
		cin>>a>>b;
		//cout<<"yes";
		//cout<<m<<endl;
		if(t==1)
		{
            merge(a,b,root);
		}
		else
		{
			a=find(a);
			f[a]+=b;
		}
		//cout<<m<<endl;
	}
	//cout<<"yes1";
	for(int i=n+1;i<root;i++)if(p[i]==i)dfs(i,0);//把每个根节点的值传递到每个计算机上
	for(int i=1;i<=n;i++)cout<<f[i]<<" ";
	return 0;
}
/*

4 8
1 1 2
2 1 10
2 3 5
1 4 1
2 2 2
1 1 2
1 2 4
2 2 1

13 13 5 3

*/

2、奶酪(NOIP2017提高组)

现有一块大奶酪,它的高度为 h,它的长度和宽度我们可以认为是无限大的,奶酪中间有许多半径相同的球形空洞。

我们可以在这块奶酪中建立空间坐标系,在坐标系中,奶酪的下表面为 z=0,奶酪的上表面为 z=h。 

现在,奶酪的下表面有一只小老鼠 Jerry,它知道奶酪中所有空洞的球心所在的坐标。

如果两个空洞相切或是相交,则 Jerry 可以从其中一个空洞跑到另一个空洞,特别地,如果一个空洞与下表面相切或是相交,Jerry 则可以从奶酪下表面跑进空洞;如果一个空洞与上表面相切或是相交,Jerry 则可以从空洞跑到奶酪上表面。

位于奶酪下表面的 Jerry 想知道,在不破坏奶酪的情况下,能否利用已有的空洞跑到奶酪的上表面去? 

空间内两点 P1(x1,y1,z1)、P2(x2,y2,z2)的距离公式如下:

输入格式

每个输入文件包含多组数据。  

输入文件的第一行,包含一个正整数 T,代表该输入文件中所含的数据组数。  

接下来是 T组数据,每组数据的格式如下:

第一行包含三个正整数 n,h,和 r,两个数之间以一个空格分开,分别代表奶酪中空洞的数量,奶酪的高度和空洞的半径。  

接下来的 n 行,每行包含三个整数 x、y、z,两个数之间以一个空格分开,表示空洞球心坐标为 (x,y,z)。

输出格式

输出文件包含 T 行,分别对应 T 组数据的答案,如果在第 i 组数据中,Jerry 能从下表面跑到上表面,则输出 Yes,如果不能,则输出 No

数据范围

1≤n≤1000
1≤h,r≤1e9
T≤20
坐标的绝对值不超过1e9

输入样例:
3 
2 4 1 
0 0 1 
0 0 3 
2 5 1 
0 0 1 
0 0 4 
2 5 2 
0 0 2 
2 0 4
输出样例:
Yes
No
Yes
思路:

多源dfs(推荐)

或者并查集

代码:

多源bfs

#include <bits/stdc++.h>
using namespace std;
int t, n, h, r, f[1010];
double x[1010], y[1010], z[1010];

inline double dist(double X1, double X2, double Y1, double Y2, double Z1, double Z2) {
    return sqrt((X1 - X2) * (X1 - X2) + (Y1 - Y2) * (Y1 - Y2) + (Z1 - Z2) * (Z1 - Z2));
}

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d%d", &n, &h, &r);
        for (int i = 1; i <= n; i++) scanf("%lf%lf%lf", &x[i], &y[i], &z[i]), f[i] = 0;
        queue<int> q; bool ok = 0;
        for (int i = 1; i <= n; i++) 
            if (z[i] <= r) q.push(i), f[i] = 1;
        while (q.size()) {
            int p = q.front(); q.pop();
            if (ok) break;
            if (z[p] + r >= h) {ok = 1; puts("Yes"); break;}
            for (int i = 1; i <= n; i++) {
                if (f[i]) continue;
                if (dist(x[p], x[i], y[p], y[i], z[p], z[i]) <= 2 * r) {
                    q.push(i), f[i] = 1;
                    if (z[i] + r >= h) {ok = 1; puts("Yes"); break;}
                }
            }
        }
        if (!ok) puts("No");
    }
    return 0;
}

并查集:

#include <bits/stdc++.h>
using namespace std;
int t, n, h, r;
int t1, s1[1010], t2, s2[1010], fa[1010];
pair<long long, pair<long long, long long> > a[1010];

int get(int x) {
    if (fa[x] != x) fa[x] = get(fa[x]);
    return fa[x];
}
double dist(double X1, double X2, double Y1, double Y2, double Z1, double Z2) {
    return sqrt(pow(X1 - X2, 2) + pow(Y1 - Y2, 2) + pow(Z1 - Z2, 2));
}

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d%d", &n, &h, &r); t1 = 0, t2 = 0;
        for (int i = 1; i <= n; i++) fa[i] = i;
        for (int i = 1; i <= n; i++) {
            scanf("%lld%lld%lld", &a[i].second.first, &a[i].second.second, &a[i].first);
            if (a[i].first + r >= h) s1[++t1] = i;
            if (a[i].first - r <= 0) s2[++t2] = i;
        }
        if (t1 == 0 || t2 == 0) {puts("No"); continue;}
        for (int i = 1; i <= n; i++)
            for (int j = i + 1; j <= n; j++) {
                if (get(i) == get(j)) continue;
                double d = dist(a[i].second.first, a[j].second.first, a[i].second.second, a[j].second.second, a[i].first, a[j].first);
                if (d <= 2 * r) fa[get(i)] = get(j);
            }
        int b = 0;
        for (int i = 1; i <= t1; i++) {
            if (b) break;
            for (int j = 1; j <= t2; j++)
                if (get(s1[i]) == get(s2[j])) {puts("Yes"); b = 1; break;}
        }
        if (!b) puts("No");
    }
    return 0;
}

3、合并集合(模板)

一共有 n 个数,编号是 1∼n,最开始每个数各自在一个集合中。

现在要进行 m 个操作,操作共有两种:

  1. M a b,将编号为 a和 b的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作;
  2. Q a b,询问编号为 a 和 b 的两个数是否在同一个集合中;
输入格式

第一行输入整数 n 和 m。

接下来 m 行,每行包含一个操作指令,指令为 M a b 或 Q a b 中的一种。

输出格式

对于每个询问指令 Q a b,都要输出一个结果,如果 a 和 b 在同一集合内,则输出 Yes,否则输出 No

每个结果占一行。

数据范围

1≤n,m≤1e5

输入样例:
4 5
M 1 2
M 3 4
Q 1 2
Q 1 3
Q 3 4
输出样例:
Yes
No
Yes
思路:

写好find函数和merge函数

代码:
#include<bits/stdc++.h>

using namespace std;

const int N=1e5+5;

int n,m;


int p[N];

int find(int x)
{
	if(x!=p[x])p[x]=find(p[x]);
	return p[x];
}

void merge(int a,int b)
{
	p[find(a)]=find(b);//a的祖先添加到b的祖先下面 
}

int main()
{
	cin>>n>>m;
	
	for(int i=1;i<=n;i++)p[i]=i;
	
	
	
	while(m--)
	{
		char op;
		int a,b;
		cin>>op;
		cin>>a>>b;
		if(op=='M')
		{
			merge(a,b);
		}
		else
		{
			if(find(a)==find(b))cout<<"Yes"<<endl;
			else cout<<"No"<<endl; 
		}
	}
	//Yes No
	return 0;
} 

4、连通块中点的数量(模板)

给定一个包含 n 个点(编号为 1∼n)的无向图,初始时图中没有边。

现在要进行 m 个操作,操作共有三种:

  1. C a b,在点 a 和点 b之间连一条边,a 和 b 可能相等;
  2. Q1 a b,询问点 a 和点 b是否在同一个连通块中,a 和 b 可能相等;
  3. Q2 a,询问点 a 所在连通块中点的数量;
输入格式

第一行输入整数 n 和 m。

接下来 m 行,每行包含一个操作指令,指令为 C a bQ1 a b 或 Q2 a 中的一种。

输出格式

对于每个询问指令 Q1 a b,如果 a和 b 在同一个连通块中,则输出 Yes,否则输出 No

对于每个询问指令 Q2 a,输出一个整数表示点 a 所在连通块中点的数量

每个结果占一行。

数据范围

1≤n,m≤1e5

输入样例:
5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5
输出样例:
Yes
2
3

思路:

cnt数组统计连通块中点的数量(注意数量全放在祖先节点),合并函数(merge)中进行累加

代码:
#include<bits/stdc++.h>

using namespace std;

const int N=1e5+10;

int n,m;

int p[N];
int cnt[N];

int find(int x)
{
	if(x!=p[x])p[x]=find(p[x]);
	return p[x];
}

void merge(int a,int b)
{
	cnt[find(b)]+=cnt[find(a)];
	p[find(a)]=find(b);
}

int main()
{
	cin>>n>>m;
	
	for(int i=1;i<=n;i++)
	{
		p[i]=i;
		cnt[i]=1;
	}
	
	while(m--)
	{
		char op[5];
		cin>>op;
		if(op[0]=='C')
		{
			int a,b;
			cin>>a>>b;
			if(find(a)==find(b))continue;
			merge(a,b);
		}
		else if(op[1]=='1')
		{
			int a,b;
			cin>>a>>b;
			if(find(a)==find(b))cout<<"Yes"<<endl;
			else cout<<"No"<<endl;
		}
		else
		{
			int t;
			cin>>t;
			cout<<cnt[find(t)]<<endl;
		}
	}
	
	
	return 0;
}

5、格子游戏(《信息学奥赛一本通》)

Alice和Bob玩了一个古老的游戏:首先画一个 n×n的点阵(下图 n=3 )。

接着,他们两个轮流在相邻的点之间画上红边和蓝边:

1.png

直到围成一个封闭的圈(面积不必为 1)为止,“封圈”的那个人就是赢家。因为棋盘实在是太大了,他们的游戏实在是太长了!

他们甚至在游戏中都不知道谁赢得了游戏。

于是请你写一个程序,帮助他们计算他们是否结束了游戏?

输入格式

输入数据第一行为两个整数 n 和 m。n表示点阵的大小,m 表示一共画了 m 条线。

以后 m 行,每行首先有两个数字 (x,y),代表了画线的起点坐标,接着用空格隔开一个字符,假如字符是 D,则是向下连一条边,如果是 R 就是向右连一条边。

输入数据不会有重复的边且保证正确。

输出格式

输出一行:在第几步的时候结束。

假如 m 步之后也没有结束,则输出一行“draw”。

数据范围

1≤n≤200
1≤m≤24000

输入样例:
3 5
1 1 D
1 1 R
1 2 D
2 1 R
2 2 D
输出样例:
4
思路:

注意审题,"轮流在相邻的点之间画上红边和蓝边"表示不存在有孤立的线的情况

可以把每个点进行转换,变成一个独特的数,然后我们就可以把每个点存起来,如果新的两个点转化后,发现有共同祖先那就表示封圈了

代码:
#include<bits/stdc++.h>

using namespace std;

const int N=4e4+9;//因为二维转化为一维了,所以一维空间必须开N的平方级 (200*200) 
int p[N];

int find(int x)
{
	if(x!=p[x])p[x]=find(p[x]);
	return p[x];
}

void merge(int a,int b)
{
	p[find(a)]=find(b);
}

int main()
{
	int n,m;
	
	cin>>n>>m;
	for(int i=1;i<=n*n;i++)p[i]=i;
	
	int cnt=1;
    for(int i=1;i<=m;i++)
    {
    	int a,b;
    	char c;
    	cin>>a>>b>>c;
    	
    	int p=(a-1)*n+b;//p表示原来的坐标 
    	
    	int q;//q表示另一端(向下或者向右) 
    	if(c=='D')q=a*n+b;
    	else q=(a-1)*n+b+1;
    	
    
    	//cout<<find(p)<<" "<<find(q)<<endl;
    	if(find(p)==find(q))
    	{
    		cout<<i;
    		return 0;
    	}
    	merge(p,q);
	}
	cout<<"draw";
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

DashVector - 阿里云向量检索服务

DashVector 文章目录 DashVector一、关于 DashVector二、使用 DashVector 前提准备1、创建Cluster&#xff1a;2、获得API-KEY3、安装最新版SDK 三、快速使用 DashVector1. 创建Client2. 创建Collection3、插入Doc4、相似性检索5、删除Doc6. 查看Collection统计信息7. 删除Coll…

jeect-boot queryFieldBySql接口RCE漏洞(CVE-2023-4450)复现

jeect-boot积木报表由于未授权的 API /jmreport/queryFieldBySql 使用了 freemarker 解析 SQL 语句从而导致了 RCE 漏洞的产生。 1.漏洞级别 高危 2.漏洞搜索 fofa app"Jeecg-Boot 企业级快速开发平台"3.影响范围 JimuReport < 1.6.14.漏洞复现 这个漏洞的…

(done) 机器学习中的方差 variance 和 偏差 bias 怎么理解?

来源&#xff1a;https://blog.csdn.net/weixin_41479678/article/details/116230631 情况1属于&#xff1a;低 bias&#xff0c;高 variance (和 human performance 相近&#xff0c;但和 验证集dev set 相远) 通常意味着模型训练轮数太多 情况2属于&#xff1a;高 bias&#…

uniapp自定义导航栏左中右内容和图标,以及点击事件

uniapp自定义导航栏左中右内容和图标&#xff0c;以及点击事件 效果&#xff1a; 页面&#xff1a; <view class"navigation-bar"><view class"navigation-bar-left" click"navigateBack"><u-icon name"arrow-left"…

StarRocks-2.5.13部署安装

1、安装jdk11 tar xf jdk-11.0.16.1_linux-x64_bin.tar.gz mv jdk-11.0.16.1 /data/soft/jdk-11 # 配置在/etc/profile中 export JAVA_HOME/data/soft/jdk-11 export CLASSPATH.:/data/soft/jdk-11/lib export PATH/data/soft/jdk-11/bin:$PATH # 验证jdk [rootdb-public-03 s…

就业班 第二阶段 2401--3.19 day4 主从复制

一、MySQL-Replication&#xff08;主从复制&#xff09; 1.1、MySQL Replication 主从复制&#xff08;也称 AB 复制&#xff09;允许将来自一个MySQL数据库服务器&#xff08;主服务器&#xff09;的数据复制到一个或多个MySQL数据库服务器&#xff08;从服务器&#xff09;…

open3d | ubuntu源码编译open3d

# clone源码 git clone https://github.com/isl-org/Open3D# 安装依赖 cd Open3D util/install_deps_ubuntu.sh# 安装anaconda3&#xff0c;略过~ conda create -n open3d_py39 python3.9 conda activate open3d_py39# 查看一下python路径 which pythonmkdir build cd build# c…

Linus进程控制

进程创建 fork 函数 在linux中fork函数时非常重要的函数&#xff0c;它从已存在进程中创建一个新进程。新进程为子进程&#xff0c;而原进程为父进程。 #include <unistd.h> pid_t fork(void); 返回值&#xff1a;子进程中返回0&#xff0c;父进程返回子进程id&#x…

GraphPad Prism 10:一站式数据分析解决方案

GraphPad Prism 10是一款功能强大的数据分析和可视化软件&#xff0c;广泛应用于生命科学研究、医学、生物、化学等多个领域。以下是对其详细功能的介绍&#xff1a; 首先&#xff0c;GraphPad Prism 10具有出色的数据可视化功能。它支持各种类型的图表和图形&#xff0c;包括…

C语言预编译#pragma宏的作用

在嵌入式编程中&#xff0c;#pragma 指令具有非常重要的作用&#xff0c;因为它允许开发者在不同的编译器之间传达特定的编译指令。由于嵌入式编程通常与硬件紧密相关&#xff0c;且资源有限&#xff0c;这些指令可以帮助开发者更有效地利用可用资源&#xff0c;优化程序&#…

【UVM_event_pool RAL TLM_2024.03.18】

event pool uvm_event 用于同步或者通信&#xff0c;由object派生 ->:trigger event :wait eventwait_trigger();//相同时间触发与等待&#xff0c;不一定能等到该事件 wait_ptrigger();//一定能等到该事件&#xff0c;在while循环中会造成一直触发uvm_pool 共享的内存空…

Github多账号切换

在开发阶段&#xff0c;如果同时拥有多个开源代码托管平台的账户&#xff0c;在代码的管理上非常麻烦。那么&#xff0c;如果同一台机器上需要配置多个账户&#xff0c;怎样才能确保不冲突&#xff0c;不同账户独立下载独立提交呢&#xff1f; 我们以两个github账号进行演示 …

51单片机中断信号的种类及应用场景

在嵌入式系统中&#xff0c;中断是一种重要的事件处理机制&#xff0c;它可以在程序执行的任何时候暂停当前任务&#xff0c;转而执行与之相关的特殊任务或事件。51单片机作为一种常见的微控制器&#xff0c;其中断功能在各种应用中起着关键作用。然而&#xff0c;对于初学者和…

深度学习中的随机种子random_seed

解释 由于模型中的参数初始化例如权重参数如下图&#xff0c;就是随机初始化的&#xff0c;为了能够更好的得到论文中提到效果&#xff0c;可以设置随机种子&#xff0c;从而减少算法结果的随机性&#xff0c;使其接近于原始结果。 设置了随机种子&#xff0c;产生的随机数都…

AI智能分析网关V4养老院视频智能监控方案

随着科技的快速发展&#xff0c;智能监控技术已经广泛应用于各个领域&#xff0c;尤其在养老院这一特定场景中&#xff0c;智能监控方案更是发挥着不可或缺的作用。尤其是伴随着社会老龄化趋势的加剧&#xff0c;养老院的安全管理问题也日益凸显。为了确保老人的生活安全&#…

2016年认证杯SPSSPRO杯数学建模D题(第一阶段)NBA是否有必要设立四分线解题全过程文档及程序

2016年认证杯SPSSPRO杯数学建模 D题 NBA是否有必要设立四分线 原题再现 NBA 联盟从 1946 年成立到今天&#xff0c;一路上经历过无数次规则上的变迁。有顺应民意、皆大欢喜的&#xff0c;比如 1973 年在技术统计中增加了抢断和盖帽数据&#xff1b;有应运而生、力挽狂澜的&am…

Web前端笔记+表单练习+五彩导航

一、笔记 表单&#xff1a;数据交互的一种方式 登录、注册、搜索 <from> <input type""> --- <input type"text"> --- 普通输入框&#xff0c;内容在一行显示 <input type"password"> --- 密码框 <input type"…

docker镜像复制与常见命令

一、前言 最近通过阿里的镜像仓库远程拉取镜像&#xff0c;发现以前的版本不见了&#xff0c;拉取了最新的镜像&#xff0c;有发现版本不配问题。那么想使用老版本的镜像那就要从别的环境获取。于是就需要进行离线镜像复制&#xff0c;打包&#xff0c;上传&#xff0c;重新导入…

【Java基础】了解Java安全体系JCA,使用BouncyCastle的ED25519算法生成密钥对、数据签名

文章目录 一.Java安全体系结构二.JCA和JCE三.CSP(加密服务提供程序)与Engine类1.CSP2.Engine类如何使用引擎类 四.查看当前JDK支持的算法服务提供商(Provider)五.BouncyCastle是什么六.如何使用BouncyCastle&#xff1f;七.bouncycastle实现ED25519工具类 一.Java安全体系结构 …

vue 消息左右滚动(前后无缝衔接)

演示效果 封装的组件 <!--* Author:* Date: 2024-03-21 19:21:58* LastEditTime: 2024-03-21 20:31:50* LastEditors: Please set LastEditors* Description: 消息左右滚动 --> <template><divid"textScroll"class"text-scroll"mousemove&…