Union-Find

板子:

非递归写法(基于链表)

public class LinkedDSU {public static final int illegal_next=-1;private static class Node{int equiv;int next;int length;Node(int e,int n,int len){equiv = e;next = n;length = len;}}private final Node[] ns;public LinkedDSU(int n){ns = new Node[n];for (int i = 0; i < ns.length; i++) {ns[i] = new Node(i,illegal_next,1);}}public void union(int x,int y){// same equiv?int ex = find(x);int ey = find(y);if(ex == ey){return;}// merge small to largeif(ns[ex].length>ns[ey].length){int et = ex;ex = ey;ey = et;}// change equivint header = ex;while(ns[header].next!=illegal_next){ns[header].equiv = ey;header = ns[header].next;}ns[header].equiv = ey;// linked list insertionns[header].next = ns[ey].next;ns[ey].next = ex;// update sizens[ey].length += ns[ex].length;}public int find(int x){return ns[x].equiv;}
}

递归写法

// LC765 official writeup
public class RecursiveDSU {private final int[] f;public RecursiveDSU(int n){f = new int[n];for (int i = 0; i < f.length; i++) {f[i] = i;}}public int getf(int x){if(f[x]==x){return x;}int newf = getf(f[x]);f[x] = newf; // path compressionreturn newf;}public void add(int x,int y){int fx = getf(x);int fy = getf(y);f[fx] = fy;}
}

核心想法:如果这个元素的源头不是他自己 说明它被归到别的等价类去了,深搜它的源头(链)

多说无益,看题。

1. LC 2812 找出最安全路径

这题我一开始二分T了。预计算写的暴力,判断写的深搜。这题预计算所有点的安全距离的方式应该是多源BFS。判断连通性的方式是DSU。所以不放在二分题单里,放在DSU。

多源BFS的大致思路:

  1. 选中初始源列表
  2. 对于当前轮次的源列表,遍历,访问每个源的所有可行的邻居(在表里并且没被访问过),放到下一轮访问的源列表中
  3. 这样就类似于一圈一圈的扩散出去

并查集判连通:由于我们想要的是最大安全系数,所以倒着搜各个安全距离对应的点集。如果发现它的邻居的安全距离大于等于它的,那么可以把它的邻居对应的等级类直接归到这个点对应的等级类。由于我们倒着搜答案,因此这个等价类的门槛会越来越低,直至把所有点都囊括进去,那个时候安全系数也就只能为0了。

import java.util.ArrayList;
import java.util.List;class Solution {static int[][] dirs = new int[][]{{-1,0},{1,0},{0,-1},{0,1}};public int maximumSafenessFactor(List<List<Integer>> grid) {// 两个关键问题// 怎么标记不能走的格子// 怎么判断能否从左上角走到右下角int n = grid.size();ArrayList<int[]> q = new ArrayList<>(); // 所有为1的网格多源bfsint[][] dis = new int[n][n];// 统计所有1for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if(grid.get(i).get(j)==1){q.add(new int[]{i,j});}else{dis[i][j] = -1; // 顺便初始化访问数组}}}ArrayList<List<int[]>> groups = new ArrayList<>();groups.add(q);List<int[]> tmp;/*** 多源bfs的滚动数组trick* 相当于一开始现有一个源的列表(多源)* 然后每次根据当前的源,访问所有源的所有邻接的邻居 (当前的源就是tmp列表)* 把每个邻居放在下一轮源的列表中* 由于用tmp接替了q的位置,所以q就变成了下一轮源的列表,这样while(!q.isEmpty())就会判断下一轮是否还有源可以用*/while(!q.isEmpty()){tmp = q; // 滚动数组省空间q = new ArrayList<>();for (int[] p : tmp) {for (int[] d : dirs) {int x = p[0]+d[0];int y = p[1]+d[1];// 下标合法并且未访问过(如果访问过,说明它被赋予了更小的值,就没必要更新了)if( x>=0 && x<n && y>=0 && y<n && dis[x][y] == -1){q.add(new int[]{x,y});// 试想如果当前是最初的那一批源会怎么样// groups.size() == 1// 也就意味着当前访问到的邻居距离最初的源的距离为1(这是因为d[0] + d[1]的abs为1,最多能造成1的位移)dis[x][y] = groups.size();}}}groups.add(q); // 最终会多出来一个空的列表}// 求最大安全系数 所以倒着搜// 并查集int[] fa = new int[n*n];for (int i = 0; i < n * n; i++) {fa[i] = i;}// 由于多源bfs多加了一个数组,倒着搜的时候要-1for(int ans = groups.size()-2;ans>0;ans--){// 安全距离为ans的点集合List<int[]> g = groups.get(ans);for (int[] p : g) {int i = p[0];int j = p[1];for (int[] d : dirs) {int x = i+d[0];int y = j+d[1];// 邻居的安全距离大于要判定的安全距离if(x>=0 && x<n && y>=0 && y<n && dis[x][y] >= ans){// 点(x,y)的类 归入到 (i,j)的等价类fa[find(fa,x*n+y)] = find(fa,i*n+j);}}}// 等级类归类完毕查看起点终点是否连通if(find(fa,0)==find(fa,n*n-1)){return ans;}}return 0;}// recursive dsu templateprivate int find(int[] fa,int x){// 如果这个元素的源头不是他自己 说明它被归到别的等价类去了,深搜它的源头(链)if(fa[x]!=x) fa[x] = find(fa,fa[x]);return fa[x];}
}

2. LC 778 水位上升的泳池中游泳

这题本来在二分题单里的,感觉能用DSU,就写了下。

思路:

  1. 将每个单元格划分为一个等级类
  2. 由于我们要找的是最短的时间,所以对时间正着搜索
  3. 搜索的思路类似于BFS,把当前的每个可以到达的位置存放入队列,随后BFS,BFS的过程中利用DSU连通节点
  4. 需要注意两点。一是如果一个节点的四周的节点并没有被访问完,那么下一轮扩散仍需要使用这个节点。另一个是扩散要持续到不能扩散为止。假设(0,0)扩散到了(1,1),那么(1,1)也需要在本轮完成扩散。
  5. 在实现4时,可以利用两个队列来回倒。在我的代码里,tmp代表了下一轮的节点。q代表当前轮的节点。所以可以看到如果这一轮扩散的某个节点的邻居没有被访问完,就把它放到tmp,下一轮接着扩散。如果一个节点的邻居被扩散到,将置入q,于本轮继续扩散。
  6. 每轮扩散,检查(0,0)和(n-1,n-1)的连通性,若连通返回答案。
import java.util.ArrayDeque;class Solution {static int[][] dirs = new int[][]{{-1,0},{0,1},{1,0},{0,-1}};public int swimInWater(int[][] grid) {int n = grid.length;int[] fa = new int[n * n];for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {fa[i*n+j] = i*n+j;}}ArrayDeque<int[]> q = new ArrayDeque<>();ArrayDeque<int[]> tmp;q.push(new int[]{0,0});boolean[] visited = new boolean[n*n];visited[0] = true;for(int i=0;i<n*n;i++){tmp = new ArrayDeque<>();while(!q.isEmpty()){int[] poll = q.poll();int x = poll[0];int y = poll[1];if(grid[x][y]>i){tmp.offer(poll);break;}boolean flag = true;for (int[] d : dirs) {int nx = x + d[0];int ny = y + d[1];if(legal(nx,ny,n) && !visited[nx*n+ny]){if(grid[nx][ny]<=i){visited[nx*n+ny] = true;fa[nx*n+ny]= find(fa,x*n+y);q.push(new int[]{nx,ny});}flag &= visited[nx*n+ny];}}if(!flag){tmp.offer(poll);}}q= tmp;if(find(fa,0) == find(fa,n*n-1)){return i;}}return n*n-1;}private boolean legal(int nx,int ny,int n){return nx>=0 && nx<n && ny>=0 && ny<n;}private int find(int[] fa,int x){if(fa[x]!=x){fa[x] = find(fa,fa[fa[x]]);}return fa[x];}
}

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

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

相关文章

优化的实时换脸项目——DeepFaceLive

DeepFaceLive是一款基于人工智能技术的换脸工具&#xff0c;可以实现实时面部捕捉和换脸效果。它利用深度学习和计算机视觉算法&#xff0c;能够以惊人的准确度和速度将脸部特征无缝地映射到任何人的脸上。DeepFaceLive的特点是可以实时换脸&#xff0c;让用户通过网络摄像头应…

银行网络安全数字化挂图作战体系建设

文章目录 前言一、网络安全数字化挂图作战的动力与支撑(一)国家层面(二)集团公司层面(三)自身层面二、网络安全数字化挂图作战的目标与定位(一)挂图作战体系设计1、总体框架设计2、安全度量框架构建3、挂图作战体系建设(二)挂图作战实施行动路径(三)挂图作战系统建…

MySQL高可用解决方案演进:从主从复制到InnoDB Cluster架构

目录 前言 1. 主从复制 主从复制的基本配置示例&#xff1a; 2. 主从复制的限制 3. InnoDB Cluster架构 InnoDB Cluster配置步骤示例&#xff1a; 4. InnoDB Cluster的优势 总结 ⭐️ 好书推荐 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

京东年度数据报告-2023全年度游戏本十大热门品牌销量(销额)榜单

同笔记本市场类似&#xff0c;2023年度游戏本市场的整体销售也呈下滑态势。根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;京东平台上游戏本的年度销量累计超过350万&#xff0c;同比下滑约6%&#xff1b;销售额将近270亿&#xff0c;同比下滑约11%。 鲸参谋综合了京东…

买卖股票的最佳时机【贪心】

Problem: 121. 买卖股票的最佳时机 文章目录 思路 & 解题方法复杂度Code 思路 & 解题方法 简单遍历一下就行。 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( 1 ) O(1) O(1) Code class Solution:def maxProfit(self, prices: List[int]) -> int:pre_min…

C语言变量与函数

目录 变量函数 变量 变量&#xff1a;计算机里的一块内存空间int a 0; 表示定义一个整型 int 变量&#xff1b;这个变量名字叫做 a “” 表示赋值&#xff1b;即将右边的 0 赋值给左边的整型变量 a 现在这一块空间 a 存放了一个值 0 这个过程也叫做整型变量 a 的初始化初始化…

C++/WinRT 简介

C/WinRT 是 Windows 运行时 (WinRT) API 的完全标准新式 C17 语言投影&#xff0c;以基于标头文件的库的形式实现&#xff0c;旨在为你提供对新式 Windows API 的一流访问。 利用 C/WinRT&#xff0c;你可以采用任何符合标准的 C17 编译器创作和使用 Windows 运行时 API。 Wind…

OSG StatsHandler 初步学习

osg为视景器的使用和调试提供了丰富的辅助组件&#xff0c;它们主要是以osg::ViewerBase的成员变量或交互事件处理器(osgGA::GUIEventHandler)的形式出现。osgViewer::StatsHandler、osg::Stats类就是其中的两个经常用到的辅助组件。 #include<osgViewer/Viewer> #inclu…

iOS xcode 15.1 打包报错

真机调试的时候没问题&#xff0c;打包的时候报错了 #报错 解决办法 pods.xcodeproj - build phases - compile sources - compiler flags pods.xcodeproj - Targets-support files pods-xx-frameworks

基类的友元类,可以访问其派生类的私有虚函数

我们知道一个基类的友元类&#xff0c;并不是其派生类的友元类 &#xff0c;但是一个基类的友元类&#xff0c;可以访问其派生类的虚函数&#xff0c;而不受访问限制 #include <iostream> class Base{friend class Test; //基类的友元类Testvirtual void f() 0; //虚…

2023年全国职业院校技能大赛应用软件系统开发赛项(高职组)赛题第6套

竞赛说明 一、项目背景 党的二十大报告指出&#xff0c;要加快建设制造强国、数字中国&#xff0c;推动制造业高端化、智能化、绿色化发展。《IDC中国制造企业调研报告&#xff0c;2021》报告指出&#xff0c;制造执行系统&#xff08;MES&#xff0c;Manufacturing Executio…

Ubuntu下git提示:终止提交因为提交说明为空。

这么简单的问题居然搜索了一会儿&#xff0c;现在的网络环境越来越差了。 解决方法&#xff1a; gedit: git config --global core.editor "gedit -s" the paramater "-s " means set the gedit mode to "standalone" Sublime Text 2 git …

GitHub Copilot的使用方法和快捷按键

GitHub Copilot是GitHub与OpenAI合作开发的一款人工智能编码助手。它基于GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型&#xff0c;可以为你提供代码补全、建议和生成的功能 使用方法&#xff1a; 安装插件&#xff1a; 首先&#xff0c;确保你的开发环…

[redis] redis的安装,配置与简单操作

一、缓存的相关知识 1.1 缓存的概念 缓存是为了调节速度不一致的两个或多个不同的物质的速度&#xff0c;在中间对速度较慢的一方起到加速作用&#xff0c;比如CPU的一级、二级缓存是保存了CPU最近经常访问的数据&#xff0c;内存是保存CPU经常访问硬盘的数据&#xff0c;而且…

LeetCode讲解篇之39. 组合总和

文章目录 题目描述题解思路题解代码 题目描述 题解思路 首先排序数组&#xff0c;然后开始选择数字&#xff0c;当选择数字num后&#xff0c;在去选择大于等于num的合法数字&#xff0c;计算过程中的数字和&#xff0c;直到选数字和等于target, 加入结果集&#xff0c;若数字和…

rhel 9 安装 nginx

1.首先在以下目录添加nginx源&#xff0c;nginx源在nginx官网可以下载。 /etc/yum.repos.d2.其次yum更新缓存 yum makecache3.接着安装nginx sudo yum install nginx4.附件nginx 1.24源&#xff0c;文件名为nginx.repo [nginx-stable] namenginx stable repo baseurlhttp:/…

AttributeError: module ‘cv2‘ has no attribute ‘SIFT‘解决总结

遇到该问题时&#xff0c;网友多是建议补个包&#xff0c;即pip install opencv-contrib-python 我在补完之后又出现下面这样的错误&#xff1a; OpenCV(3.4.3) C:\projects\opencv-python\opencv_contrib\modules\xfeatures2d\src\sift.cpp:1207: error: (-213:The function/f…

关于镜头选型时的一些注意事项

1、问题背景 最近的项目调试过程中&#xff0c;遇到与镜头相关的问题比较多。所以本文主要总结一下镜头选型时需注意的事项&#xff0c;保证在项目前期就能规避掉一些问题&#xff0c;避免项目延期。 2、问题分析 我们拿到手的一般都是摄像头模组&#xff0c;在进行摄像头调试时…

JsonPath

JsonPath是一种用于处理JSON数据的查询语言&#xff0c;它允许你通过路径表达式在JSON文档中查找和访问节点。JsonPath的语法相对简单&#xff0c;采用了开发语言友好的表达式形式。它将JSON数据转换为DOM树状结构&#xff0c;并提供在数据结构树中寻找节点的能力。 JsonPath的…

114.QTimer类和QWidget类

目录 一、QTimer类 定时器使用举例&#xff1a; 二、QWidget类 2.1设置父对象 2.2窗口位置 2.3窗口尺寸 2.4窗口标题和图标 2.5信号 2.6槽函数 示例代码&#xff1a; 一、QTimer类 QTimer 是 Qt 中用于实现定时器的类。它可以在一定的时间间隔内发射信号&#xff0c;…