连通块中点的数量-java

2024-06-01 09:44
文章标签 java 数量 中点 连通

本文主要是介绍连通块中点的数量-java,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

本次我们通过连通块中点的数量来加深我们对并查集的基本操作和原理,并且知道如何在并查集中添加附属信息。

目录

前言☀

一、连通块中点的数量☀

二、算法思路☀

1.无向图🌙

2.在a b之间连一条边,a b可能相等🌙

3.询问a和b是否在一个连通块中,a和b可能相等🌙

4.询问点所在连通块中点的数量🌙

三、代码如下☀

1.代码如下:🌙

2.读入数据🌙

3.代码运行结果🌙

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≤100000

二、算法思路☀

1.无向图🌙

图1.1无向图示例

我们有各种各样的点,然后通过一条边进行连接,且这条边没有方向,例如A与B之间有条边,那么A可以到达B,B也可以到达A;图1.1就是一个无向图。

我们还是引入一个一维整型数组p来存储各个结点的父结点的编号,p数组的索引就表示哪个结点。在这道题中我们还需要引入一个一维整型数组size,用来记录每个集合内结点的个数即我们题上说的连通块内点的个数;规定只有根节点的size数组内的值是有效的

        for(int i = 1;i <= n;i++){p[i] = i;size[i] = 1;}

 这道题跟并查集类似,我们还是需要一个find方法来找到结点x所在集合的根节点的编号。

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

对于上述find方法代码如果不太理解的,可以去看我之前写的合并集合的博客(https://blog.csdn.net/m0_63267251/article/details/139294176)里面,里面有详细的解释。

2.在a b之间连一条边,a b可能相等🌙

 图2.1添加边样例图

在这道题中我们往两个点中添加边,a和b如果相等,那么就是一个点自连如图2.1右边所示。还有可能两个点之间已经右边,然后有重复添加了一条边。

图2.2size数组维护 

 我们要添加边,其实就相当于我们把两个集合给合并了一样,例如我们在a和b两个点添加一条边,其实就是将a和b所在的两个集合合并,那么我们只需要找到b所在集合的根节点,然后让b所在集合根节点的父结点变成a所在集合的根节点就完成了合并操作即p[find(b)] = find(a);

 我们还有一个很重要的操作需要维护size数组里面的值,因为我们相当于把b所在集合放到了a所在集合的下面,那么我们只需要将所在a结点集合结点个数加上b所在集合对应的结点个数即可,我们规定了只有根节点的size值是有效的,那么我们只需要 size[find(a)] += size[find(b)]就可完成上述操作。

当然如果a结点和b结点在同一个集合的话,我们就不需要进行size数组的维护了,中间加一个判断。‘

                if(cmd.equals("C")){a = sc.nextInt();b = sc.nextInt();//当a和b已经在一个集中当中,就不需要再改变对应根节点的size值了,不在进行后续size        数组值的更新和根节点值得改变if(find(a) == find(b)){continue;}size[find(a)] += size[find(b)];p[find(b)] = find(a);

3.询问a和b是否在一个连通块中,a和b可能相等🌙

图3.1连通块示例 

 判断两个点是不是在一个连通图中,即a可以到达b,b也可以到达a,就说明两个点是在一个连通图中。如上图3.1中圈起来的就是一个连通图。

我们只需要判断一下结点a所在集合的根节点的值和结点b所在集合的根节点的值是否相等就可判断出是否在同一个连通块中。

    find(a) == find(b) ? "Yes":"No"

4.询问点所在连通块中点的数量🌙

图4.1示例图 

如图4.1所示我们可以看到点1的连通块中有3个点,点4所在的连通块中的点的数量是1。

这里我们只需要返回对应点所在集合的根节点的size数组值就是集合所在连通块中点的个数

    size[find(a)]

三、代码如下☀

1.代码如下:🌙


import java.util.*;
import java.io.*;
public class Main {static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static int N = 100010;static int[] p = new int[N];//用来记录对应结点的集合内所有点的个数static int[] size = new int[N];public static void main(String[] args)throws Exception {Scanner sc = new Scanner(br);int n = sc.nextInt();for(int i = 1;i <= n;i++){p[i] = i;size[i] = 1;}int m = sc.nextInt();while (m-- > 0){String cmd = sc.next();int a,b;if(cmd.equals("C")){a = sc.nextInt();b = sc.nextInt();//当a和b已经在一个集中当中,就不需要再改变对应根节点的size值了if(find(a) == find(b)){continue;}size[find(a)] += size[find(b)];p[find(b)] = find(a);} else if (cmd.equals("Q1")) {a = sc.nextInt();b = sc.nextInt();pw.println(find(a) == find(b) ? "Yes":"No");} else if (cmd.equals("Q2")) {a = sc.nextInt();pw.println(size[find(a)]);}}pw.flush();}public static int find(int x){if(p[x] == x){return x;}return p[x] = find(p[x]);}}

2.读入数据🌙

5 5
C 1 2
Q1 1 2
Q2 1
C 2 5
Q2 5

3.代码运行结果🌙

Yes
2
3

4.代码样例解释🌙

C 1 2 后1和2在同一个集合;Q1 1 2查询1和2是否在同一个集合打印Yes;Q2 1查询1所在集合点的个数为2;C 2 5 将2和5想连,那么1 2 5在同一个集合;Q2 5查询5所在集合点的个数为3。


总结☀

上述通过连通块中点的数量这道题又训练了一遍并查集的基本操作,本质和并查集的代码并无差别,只是我们在并查集的操作过程中可以加入一些维护信息。

这篇关于连通块中点的数量-java的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1020654

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount