日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++ 并查集模板

發布時間:2025/3/15 c/c++ 56 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++ 并查集模板 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

并查集一般在遇到求解冗余關系,關系合并,環的數量等問題的時候使用。不需要對各數值進行輸出。

注意與有向無環圖問題進行區分!

有向無環圖模板看這里:有向無環圖講解及模板(C++代碼)_子木呀的博客-CSDN博客_c++ 有向無環圖

并查集是一個很優美的數據結構,很多情況下,提煉問題后,可以用并查集進行解決,這里總結下并查集的模板及注釋,可以直接用

1.并查集的使用:

//初始化并查集 int n = xx.size(); UnionFindSet dsu(n);//初始化并查集//將兩個點合并 for(int i = 0; i < n; i++){dsu.merge(xx[i], xx[i])//...... }

2.并查集模板(直接用就行,可以根據需要修改返回值出代碼)?

有兩處優化:(1)查詢優化 (2)路徑優化

//并查集實現 class UnionFindSet{vector<int> F;//并查集容器vector<int> rank;//秩優化(如果兩個都有很多元素的根節點相遇,將根節點選為元素較少的那一個,可以節省時間)int n;public://并查集初始化UnionFindSet(int _n){n = _n;F.resize(n);rank.resize(n, 1);for(int i = 0; i < n; i++){F[i] = i;}}//并查集查詢操作int find(int x){return x == F[x] ? x : F[x] = find(F[x]);//查詢優化。找到x的根節點}//并查集合并操作bool merge(int x, int y){int fx = find(x), fy = find(y);if(fx == fy) return false;//兩個節點連在同一個根節點上則直接返回 不再合并//因為是將節點數少的連接到節點數多的節點上,當fx下面的節點數小于fy下面的節點數時,交換fx和fy//即兩個根節點相遇時,將新的根節點選為節點數較多的那一個,盡量減少find(x)的次數if(rank[fx] < rank[fy])//合并優化swap(fx, fy);F[fy] = fx;//將fy連到fx上(將節點數少的連接到節點數多的上面)rank[fx] += rank[fy];//將fy連到fx后 fx下面的節點數目要更新return true;} };

結合輸入的方式,不使用類。完全可以用的一個示例:

#include <iostream> #include<vector> #include<string> #include <unordered_map> #include <unordered_set> #include <queue> #include <algorithm>//算法頭文件 #include <numeric> #include <stack> #include<typeinfo> using namespace std;vector<int> F; // 初始化 void UnionFindSet(int N) {F.resize(N + 1, -1);//如果初始化是從1開始,這里就得用N+1 如果從0開始初始化 就用N(從多少開始初始化 根據輸入的數據進行調整)for (int i = 1; i <= N; i++){F[i] = i; // 初始化時, 將自己初始化為自己的領導} }// 查找 int find(int n) {return n == F[n] ? n : find(F[n]); }// 合并 這里直接在主程序里調用了查找 能夠省去調用合并函數的次數 void merge(int leaderX, int leaderY) {if (leaderX < leaderY){F[leaderX] = leaderY;}else{F[leaderY] = leaderX;} }// 輸入數組, 每一行表示一個集合關系, 比如第一行表示3和4屬于一個集合 int input[] = {1, 4,2, 5,3, 6,4, 2,5, 1,6, 3, };int main() {int N;cin >> N;int numberOfSets = N;// 初始化領導UnionFindSet(N);int n = sizeof(input) / sizeof(input[0]) / 2;//這地方根據輸入的形式調整int j = 0;for (int i = 0; i < n; i++){int u = input[j++];int v = input[j++];u = find(u);//這里直接在主程序里調用了查找 能夠省去調用合并函數的次數v = find(v);if (u != v) { //如果沒關系 就合并 最后numberOfSets就是不能合并的個數 也就是有幾個圈子merge(u, v);numberOfSets--;}}cout << numberOfSets << endl;return 0; }

統計某個節點下掛了多少個節點

#include <iostream> #include<vector> #include<string> #include <unordered_map> #include <unordered_set> #include <queue> #include <algorithm>//算法頭文件 #include <numeric> #include <stack> #include<typeinfo> using namespace std; vector<int> F; // 初始化 void UnionFindSet(int N) {F.resize(N + 1, -1);//如果初始化是從1開始,這里就得用N+1 如果從0開始初始化 就用N(從多少開始初始化 根據輸入的數據進行調整)for (int i = 1; i <= N; i++){F[i] = i; // 初始化時, 將自己初始化為自己的領導} }// 查找 int find(int n) {return n == F[n] ? n : find(F[n]); }int main() {int N, M;cin >> N >> M;vector<vector<int>> input;vector<int> intput1;int a,b;for (int i = 0; i < M; i++) {cin >> a >> b;intput1.push_back(a);intput1.push_back(b);input.push_back(intput1);}// 初始化領導UnionFindSet(N);for (int i = 0; i < M; i++){int u = input[i][0];int v = input[i][1];u = find(u);//這里直接在主程序里調用了查找 能夠省去調用合并函數的次數v = find(v);if (u != v) { //如果沒關系 就合并 最后numberOfSets就是不能合并的個數 也就是有幾個圈子F[v] = u;}}int numberOfSets = 0;for (int i = 0; i < F.size(); i++) {if (F[i] == 1)numberOfSets++;}cout << numberOfSets+1 << endl;return 0; }

總結

以上是生活随笔為你收集整理的C++ 并查集模板的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。