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

news2024/12/27 13:48:57

目录

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;
}

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

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

相关文章

win10下自由切换多版本JDK操作

1.在window 系统变量 path路径追加%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin; 2.下载多版本jdk zip文件解压到到C:\Program Files\Java\目录下 3.定义切换Java版本的bat文件,内容如下 @echo off @echo -------------------welcome to use Java version switch service------------…

设计模式 之 简单工厂模式+工厂模式

简单工厂模式 创建一个工厂类&#xff0c;对实现了同一个接口的多个类进行实例的创建。 //抽象类 人 public abstract class HuMan {public abstract void Talk(); } //黑人实现类 public class BlackHuman : HuMan {public override void Talk(){Console.WriteLine("I a…

python的ITS 信息平台的设计与实现flask-django-nodejs-php

第二&#xff0c;陈列说明该系统实现所采用的架构、系统搭建采用的服务器、系统开发环境和使用的工具&#xff0c;以及系统后台采用的数据库。 最后&#xff0c;对系统进行全面测试&#xff0c;主要包括功能测试、查询性能测试、安全性能测试。 分析系统存在的不足以及将来改进…

新材料正在加速金属3D打印的应用步伐

在金属3D打印领域&#xff0c;材料性能是影响工件综合表现的关键因素&#xff0c;如强度、硬度、耐腐蚀性、抛光性能以及导热性能等&#xff0c;都与材料息息相关&#xff0c;好的材料是推动金属3D打印向更多领域应用的基础。 在这一背景下&#xff0c;上海毅速新材料推出的多款…

二十二 超级数据查看器 讲解稿 其他高级功能

二十二 超级数据查看器 讲解稿 其他高级功能 ​​点击此处 以新页面 打开B站 播放当前教学视频 点击访问app下载页面 百度手机助手 下载地址 ​ 这节课我们讲超级数据查看器高级功能2&#xff0c;讲的是设置密码以外的其他功能。 进入高级功能&#xff0c;先讲一下列表样…

【MySQL】理解关系型数据库&数据的数据模型

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

优化选址问题 | 基于节约算法求解考虑碳排放及带时间窗的物流选址问题附matlab代码

目录 问题代码问题 节约算法(Savings Algorithm)通常用于解决车辆路径问题(Vehicle Routing Problem, VRP),特别是当需要考虑如何有效地组织车辆的路线以最小化总行驶距离时。然而,当问题扩展到包括碳排放和带时间窗的物流选址问题时,算法需要相应的调整。 在这个扩展…

软考高级:软件架构评估概述和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

WM8978 —— 带扬声器驱动程序的立体声编解码器(6)

接前一篇文章&#xff1a;WM8978 —— 带扬声器驱动程序的立体声编解码器&#xff08;5&#xff09; 九、寄存器概览与详解 1. 整体概览 WM8978芯片共有58个寄存器&#xff0c;整体总表如下&#xff1a; 2. 详细说明 在此&#xff0c;只介绍WM8978较为常用的那些寄存器。 &…

Java NIO和IO之间的区别

前言 NIO&#xff08;New IO&#xff09;&#xff0c;这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的&#xff0c;但实现方式不同&#xff0c;NIO主要用到的是块&#xff0c;所以NIO的效率要比IO高很多。在Java API中提供了两套NIO&#xff0c;一套是针对标准输入输出…

【Spring 事务详解】声明式事务概念

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

element-plus下拉框和输入框宽度不一致,:popper-append-to-body=“false“失效

遇到的问题&#xff1a;我修改了el-select输入框的宽度之后&#xff0c;发现下拉选项和输入框的宽度不一样了! 2. 原因控制台看到下拉项的DOM元素时插入到body里面了&#xff0c;使用:popper-append-to-body"false"发现已经废弃&#xff0c;最后发现替换成:teleporte…

Android 动态类加载实现免安装更新

随着Html5技术成熟&#xff0c;轻应用越来越受欢迎&#xff0c;特别是其更新成本低的特点。与Native App相比&#xff0c;Web App不依赖于发布下载&#xff0c;也不需要安装使用&#xff0c;兼容多平台。目前也有不少Native App使用原生嵌套WebView的方式开发。但由于Html渲染特…

宜搭低代码高级认证实操题2 faas连接器加密解密

密钥维护页-保证有一条数据 敏感信息提交页 存档页&#xff0c;只是用来存数据的审批的时候不用这个表提交数据不然会出两条 授权查看页 FaaS连接器先下载好他的示例代码然后按照要求配置好参数直接拷贝进去就行 然后需要在云开发环境里面先new一个terminal然后跑一下./builde…

全智能深度演进,一键成片让视频创作颠覆式提效

全智能一键成片&#xff0c;让内容创作的「边际成本」逼近于零。 大模型和AIGC技术的发展&#xff0c;可以用“日新月异”来形容&#xff0c;其迭代速度史无前例&#xff0c;涌现出的各类垂直应用模型&#xff0c;也使得音视频行业的应用场景更加广泛和多样化。 然而&#xff…

Mora: Enabling Generalist Video Generation via A Multi-Agent Framework

Mora: Enabling Generalist Video Generation via A Multi-Agent Framework PDF: https://arxiv.org/html/2403.13248v1 1 概述 为弥补Sora不开源的缺陷&#xff0c;本文提出多代理框架Mora&#xff0c;整合先进视觉AI代理&#xff0c;复制Sora的全能视频生成能力。Mora能利用…

目标检测——PP-YOLOE-R算法解读

PP-YOLO系列&#xff0c;均是基于百度自研PaddlePaddle深度学习框架发布的算法&#xff0c;2020年基于YOLOv3改进发布PP-YOLO&#xff0c;2021年发布PP-YOLOv2和移动端检测算法PP-PicoDet&#xff0c;2022年发布PP-YOLOE和PP-YOLOE-R。由于均是一个系列&#xff0c;所以放一起解…

网络带宽 (网速) 在线测试

网络带宽 [网速] 在线测试 1. 测网速2. SPEEDTEST3. 下载、上传4. 宽带速率对照表5. 时延6. 抖动7. 丢包8. 测速节点9. 网线References 1. 测网速 https://www.speedtest.cn/ 2. SPEEDTEST https://www.speedtest.net/ ​ 3. 下载、上传 网络数据传输分为发送数据和接收数据…

Uni-app/Vue/Js本地模糊查询,匹配所有字段includes和some方法结合使用e

天梦星服务平台 (tmxkj.top)https://tmxkj.top/#/ 1.第一步 需要一个数组数据 {"week": "全部","hOutName": null,"weekendPrice": null,"channel": "门市价","hOutId": 98,"cTime": "…

WM8978 —— 带扬声器驱动程序的立体声编解码器(5)

接前一篇文章&#xff1a;WM8978 —— 带扬声器驱动程序的立体声编解码器&#xff08;4&#xff09; 九、寄存器概览与详解 1. 整体概览 WM8978芯片共有58个寄存器&#xff0c;整体总表如下&#xff1a; 2. 详细说明 在此&#xff0c;只介绍WM8978较为常用的那些寄存器。 &…