藍橋杯高頻考點——并查集(心血之作)

并查集

  • TA Can Do What & why learning
    • what
    • why
  • 原理和結構
  • 路徑壓縮
  • 例題講解
    • 題解
      • solution 1(50分)
      • solution 2(100分)
  • 按秩(樹高)合并
  • 按大小合并

TA Can Do What & why learning

what

在這里插入圖片描述

并查集主要是解決連通塊的問題,例如對于上面的這個由5個村子若干條路構成的簡易地圖,如果問你1----->5是否是連通的,顯然是的,那如果問你3——>5是否連通,顯然是false,因為沒有任何一條路能從3指向5,這不是很簡單嗎

why

那我們需要并查集干嘛?

好問題 如果這個圖如果需要你自己構造而不是直接給你(動態構造集合關系),你很難或者說沒法直接通過給的數據去畫出每一個圖的時候,并查集就能幫助我們迅速判斷是否連通,而往往算法競賽中的題目都是動態構造的(后面會附上例題),所以學習并查集是很有必要的,不然的話很大概率會超時
傳統方式:
假設你有 100 萬個村莊,每次新增一條路(動態添加邊),如果每次都用 DFS/BFS 重新遍歷整個圖來判斷兩個村莊是否連通,時間復雜度會高達 O (N),效率極低。而并查集的find和union操作經過路徑壓縮和按秩合并優化后,時間復雜度幾乎是O(1)

原理和結構

我們需要知道兩個概念父節點和祖先,有一點像二叉樹章節里的但又不太一樣,尤其是對于祖先這個概念,
祖先代表的是:某一個節點不斷去尋找他的父節點(遞歸),直到某一個節點的父節點是他本身(出口)

題外話:我在學習的時候感覺有點像 二叉樹章節里面的 求最大深度問題,其實后來我想了一下是很正常的
畢竟樹從某種意義上來說是特殊的圖

言歸正傳:我們用一個pre數組來保存每個節點的父親,我們的數組如下圖所示,這里特意需要說的就是 1的父親是他本身,所以1對應pre數組里頭存儲的父節點就是1

這句話怎么來理解呢:
其實可以把1看做是上面這個集合(1,2,4,5)的代表元素,也就是根節點,打個比方來說,這個1就是這個集合(家族)里面最年長的,就像家族的 “掌門人” 一樣,沒有比他更年長的父親了,所以他的父親就是他自己。
成員 1 作為這個家族的代表元素(根節點),就像是整個家族的源頭,其他成員都是從他這里 “衍生” 出來的,就像一棵大樹,成員 1 是樹干最頂端的那個起始點,其他成員是從樹干上長出來的樹枝和樹葉。

在這里插入圖片描述

通過上面的例子大家應該會有一個比較基礎的了解,但是在一開始每一個節點都是跟自己是一個連通關系(即指向自身)
在這里插入圖片描述
就比如在添加1-2這條邊的時候,我們就會讓2的祖先指向1,在添加2-4這條邊的時候,我們就需要注意,打個比方來說
由于2的“錢”已經交給1了,4想要找2要錢是找不到的,只能去找1了,體現在圖中就是讓4的祖先指向1,
總結來說就是:對于任何非根節點的相連都必須轉換成它們各自的根節點相連

那現在我們已經可以用個構建的這個表來判斷節點之間是否連通了,就比如1一直找,找到他的祖先是4,這個時間復雜度是O(N)的,但是這只是一次查詢的情況如果有n次查詢,那么時間復雜度就是O(n方),
那么有沒有辦法去優化它呢?
其實是有的——路徑壓縮(沒學之前聽著恐怖 其實是紙老虎)
在這里插入圖片描述

路徑壓縮

我對于路徑壓縮的理解(可能不完全準確哈):
就是好比你是一個失憶的人,現在知道四個地方,A B C D,你通過不斷探索知道了A是經過B C 能走到D的,也就是說你現在知道A到D是連通的,但是每過一段時間 如果一個人問你,你都需要重新走一遍,路徑壓縮好比就是,你用筆記本記下來了,A到D是通的并且D是終點,(這就引出了路徑壓縮的核心思想:通過直接記錄最終結果(根節點),避免重復計算路徑)
同理B,C到D也是通的,我們這里并不關心,A怎么到D,只關心從A能不能到D

壓縮完成就是這個情況:
在這里插入圖片描述

本質:
犧牲空間(存儲父指針)換取時間(快速查詢)
將樹的高度 “壓扁”,使得后續的find操作時間復雜度接近 O (1)

這里壓扁的是啥?不就是我們尋找的路徑path嗎

例題講解

在這里插入圖片描述

題解

題目說的很直白就是讓你用并查集的思路,其中有一個flag Z當它變化的時候,分別對應兩種操作:1.合并(merge)2.判斷(isCon)

solution 1(50分)

還有50%的測試點,數據非常大,即便關閉同步流,還是超時了嗎,還是做不到嗎,哈基霜你這家伙…
在這里插入圖片描述

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 9;
int pre[maxn];//存儲父節點int root(int x)
{return pre[x] == x ? x : pre[x] = root(pre[x]);
}
//一切操作都在根上
void Merge(int x, int y)
{pre[root(x)] = root(y);
}bool isCon(int x, int y)
{return root(x) == root(y);
}void init(int N)
{for (int i = 1; i <= N; ++i) pre[i] = i;
}signed main()
{ios::sync_with_stdio(0);int N, M;cin >> N >> M;init(N);while (M--){int Z, X, Y;cin >> Z >> X >> Y;if (Z == 1)Merge(X, Y);else if (Z == 2)printf("%c\n", isCon(X, Y) ? 'Y' : 'N');}return 0;
}

solution 2(100分)

之前代碼僅實現路徑壓縮,未結合按樹高或者大小合并,在數據量大 時,樹可能因合并順序不當變得高度很高,導致find操作時間復雜度退化為接近O(n),最終超時。而當前代碼通過兩種優化,將單次操作的時間復雜度優化至幾乎常數級

#include <bits/stdc++.h>
using namespace std;const int maxn = 1e5 + 9;
int pre[maxn];// 存儲父節點
int siz[maxn];// 存儲集合大小(模擬秩)// 初始化并查集
void init(int N) {for (int i = 1; i <= N; ++i) {pre[i] = i;siz[i] = 1; // 初始時每個集合大小為 1}
}// 查找根節點并路徑壓縮
int root(int x) {return pre[x] == x ? x : pre[x] = root(pre[x]);
}// 合并兩個集合,按集合大小(秩)優化
void Merge(int x, int y) {int rx = root(x);int ry = root(y);if (rx == ry) return; // 已在同一集合,無需合并// 保證將較小集合合并到較大集合if (siz[rx] > siz[ry]) swap(rx, ry); pre[rx] = ry;if (siz[rx] == siz[ry]) siz[ry]++; // 若大小相等,合并后新集合秩+1
}// 判斷兩個元素是否連通
bool isCon(int x, int y) {return root(x) == root(y);
}signed main() {ios::sync_with_stdio(0);int N, M;cin >> N >> M;init(N);while (M--) {int Z, X, Y;cin >> Z >> X >> Y;if (Z == 1) {Merge(X, Y);} else if (Z == 2) {printf("%c\n", isCon(X, Y) ? 'Y' : 'N');}}return 0;
}

這就引出了下面的優化方法按秩合并和啟發式合并

按秩(樹高)合并

在這里插入圖片描述
在這之前啊,我們是不是通過解決 斜樹查找退化成鏈表的問題 學習過平衡二叉樹的概念,
這個其實跟這里的按秩合并非常像,解決的問題也很像

比如說上面這張圖,如果新增的邊是4->3,
那拿3這個節點舉例,那他走到根只需要兩步,那如果是3->4,那就需要走3步,根節點向右傾斜了

對于一棵樹 我們更希望它變成 矮墩墩 而不是長竹竿,所以就需要我們添加邊的時候就需要進行比較 矮的指向高的
在這里插入圖片描述

按大小合并

跟上面跟類似用小的集合指向大的集合 也就是比較少的點會多走一步

void Merge(int x, int y) {int rx = root(x);int ry = root(y);if (rx == ry) return; // 已在同一集合,無需合并// 保證將較小集合合并到較大集合if (siz[rx] > siz[ry]) swap(rx, ry); pre[rx] = ry;if (siz[rx] == siz[ry]) siz[ry]++; // 若大小相等,合并后新集合秩+1
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/898680.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/898680.shtml
英文地址,請注明出處:http://en.pswp.cn/news/898680.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

抖音視頻數據獲取實戰:從API調用到熱門內容挖掘

在短視頻流量為王的時代&#xff0c;掌握抖音熱門視頻數據已成為內容運營、競品分析及營銷決策的關鍵。本文將手把手教你通過抖音開放平臺API獲取視頻詳情數據&#xff0c;并提供完整的代碼實現及商業化應用思路。 一、抖音API權限申請與核心接口 抖音API需企業資質認證&…

香橙派連接攝像頭過程

在香橙派上下載NoMachine 在控制電腦上也下載NoMachine sudo nmcli dev wifi connect "你的WiFi名稱" password "你的WiFi密碼" 連接上wifi后就可以在NoMachine連上香橙派了 &#xff08;不過前提是香橙派有安裝桌面端系統&#xff08;非僅窗口端&…

SOFABoot-08-啟動加速

前言 大家好&#xff0c;我是老馬。 sofastack 其實出來很久了&#xff0c;第一次應該是在 2022 年左右開始關注&#xff0c;但是一直沒有深入研究。 最近想學習一下 SOFA 對于生態的設計和思考。 sofaboot 系列 SOFABoot-00-sofaboot 概覽 SOFABoot-01-螞蟻金服開源的 s…

簡單實用!百度AI + Raphael AI = 免費生圖

簡單實用&#xff01;百度AI Raphael AI 免費生圖 -- ![在這里插入圖片描述](https://i-blog.csdnimg.cn/direct/b55eda9141d34697b05db0cd60f62b75.png#pic_center) 第一步&#xff1a;下載或截取一些好看的圖片當參考圖片 第二步&#xff1a;用百度AI描述你想要的圖片&…

React中組件通訊與插槽

一、為DOM組件設置Props 1.用JSX語法對標簽的類名進行設置屬性名是className&#xff1b; 2.用JSX語法對標簽的樣式進行設置要使用鍵值對進行設置&#xff0c;帶“-”時用小駝峰方法來書寫&#xff1b; 3.當一個標簽的屬性過多時&#xff0c;可以通過JSX語法進行展開設置&am…

自定義reset50模型轉換到昇騰om

目錄 原始轉換腳本 腳本運行報錯 基于reset50 模型的自定義網絡 基本網絡結構 卷積模塊定義示例 Bottleneck定義示例 網絡定義示例 改進的轉換腳本 腳本運行報錯channels不匹配 腳本運行報錯維度不匹配 模型輸入數據的類型 tensor size NCHW和NHWC 自定義網絡的通…

vue3:十一、主頁面布局(進入指定菜單頁面,默認鎖定到左側菜單)

一、效果 直接進入home頁面&#xff0c;直接展開對應的菜單項 二、具體實現 1、菜單容器增加默認選中變量 在菜單容器中將默認展開菜單default-openeds修改為默認選中菜單default-active 2、引入useRoute方法 引入該方法為了獲取當前頁面的路徑 import { useRoute } from …

六十天前端強化訓練之第二十七天之Pinia 狀態管理全解與購物車實戰案例

歡迎來到編程星辰海的博客講解 看完可以給一個免費的三連嗎&#xff0c;謝謝大佬&#xff01; 目錄 一、Pinia 深度解析 1. Pinia 核心設計 2. 核心概念圖解 3. Store 類型對比 Option Store&#xff08;選項式&#xff09; Setup Store&#xff08;組合式&#xff09; …

計算機網絡技術服務管理基于Spring Boot-SSM

目錄 一、引言 二、用戶需求分析 三、功能介紹 ??3.1.資源管理?&#xff1a; ?3.2.故障管理?&#xff1a; ?3.3.性能管理?&#xff1a; ?3.4.安全管理?&#xff1a; ?3.5.配置管理?&#xff1a; ?3.6.日志管理?&#xff1a; ?3.7.用戶管理?&#xff1…

深度學習驅動下的字符識別:挑戰與創新

一、引言 1.1 研究背景 深度學習在字符識別領域具有至關重要的地位。隨著信息技術的飛速發展&#xff0c;對字符識別的準確性和效率要求越來越高。字符識別作為計算機視覺領域的一個重要研究方向&#xff0c;其主要目的是將各種形式的字符轉換成計算機可識別的文本信息。近年…

Java多線程與高并發專題——Future 是什么?

引入 在上一篇Callable 和 Runnable 的不同&#xff1f;的最后&#xff0c;我們有提到和 Callable 配合的有一個 Future 類&#xff0c;通過 Future 可以了解任務執行情況&#xff0c;或者取消任務的執行&#xff0c;還可獲取任務執行的結果&#xff0c;這些功能都是 Runnable…

【vue的some和filter】

在 Vue 中&#xff0c;some 和 filter 是兩種不同的數組方法&#xff0c;分別用于處理數據篩選和條件判斷。以下是它們在 Vue 中的具體用法和區別&#xff1a; 一、filter 方法 作用&#xff1a;對數組進行過濾&#xff0c;返回符合條件的新數組。 使用場景&#xff1a;常用于…

用ArcGIS做一張符合環評要求的植被類型圖

植被類型圖是環境影響評價&#xff08;環評&#xff09;中的重要圖件&#xff0c;需滿足數據準確性、制圖規范性和信息完整性等要求。本教程將基于ArcMap平臺&#xff0c;從數據準備到成果輸出&#xff0c;詳細講解如何制作符合環評技術規范的植被類型圖。 ArcGIS遙感解譯土地…

Fourier-Lerobot——把斯坦福人形動作策略iDP3封裝進了Lerobot(含我司七月人形研發落地實踐)

前言 近期在摳lerobot源碼時&#xff0c;看到其封裝了ALOHA ACT、diffusion policy、π0時&#xff0c;我就在想&#xff0c;lerobot其實可以再封裝下idp3 我甚至考慮是否從我聯合帶的那十幾個具身研究生中選幾個同學做下這事&#xff0c;對他們也是很好的歷練然當25年3.18日…

MySQL拒絕訪問

1. 問題 使用圖形界面工具連接MySQL數據庫&#xff0c;拒絕訪問&#xff01; 2. 解決方法 以管理員的身份打開cmd&#xff0c;輸入命令&#xff0c;啟動MySQL net start mysql版本號 3. 參考 暫無

多模態SVG生成新標桿:StarVector從圖像文本生成高精度SVG的AI模型

一、引言&#xff1a;矢量圖形的崛起與挑戰 在現代數字世界中&#xff0c;圖像扮演著至關重要的角色&#xff0c;而可伸縮矢量圖形&#xff08;SVG&#xff09;正因其獨特的優勢&#xff0c;在網頁設計、圖形設計等領域占據著越來越重要的地位。與傳統的基于像素的柵格圖像不同…

Netty——BIO、NIO 與 Netty

文章目錄 1. 介紹1.1 BIO1.1.1 概念1.1.2 工作原理1.1.3 優缺點 1.2 NIO1.2.1 概念1.2.2 工作原理1.2.3 優缺點 1.3 Netty1.3.1 概念1.3.2 工作原理1.3.3 優點 2. Netty 與 Java NIO 的區別2.1 抽象層次2.2 API 易用性2.3 性能優化2.4 功能擴展性2.5 線程模型2.6 適用場景 3. 總…

游戲引擎學習第175天

回顧和今天的計劃 今天的主要任務是完成稀疏 Unicode 支持。之前我們已經完成了所有的思考和設計工作&#xff0c;但代碼部分尚未完成&#xff0c;因為有許多內容需要調整和重構。因此&#xff0c;今天的目標就是把這些內容全部整理好并最終實現。 回顧當前測試資源構建器的狀…

零基礎上手Python數據分析 (7):Python 面向對象編程初步

寫在前面 回顧一下,我們已經學習了 Python 的基本語法、數據類型、常用數據結構和文件操作、異常處理等。 到目前為止,我們主要采用的是 面向過程 (Procedural Programming) 的編程方式,即按照步驟一步一步地編寫代碼,解決問題。 這種方式對于簡單的任務已經足夠,但當程序…

CNN的空間歸納偏置(Inductive Bias):深入解析其本質與影響(與transformer的比較)

CNN的空間歸納偏置&#xff08;Inductive Bias&#xff09;&#xff1a;深入解析其本質與影響 在深度學習領域&#xff0c;卷積神經網絡&#xff08;Convolutional Neural Networks, CNN&#xff09;和Transformer代表了兩種截然不同的設計哲學。CNN憑借其卓越的性能長期主導計…