<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      并查集(Union Find Set)

      1 基本介紹

      并查集是一種用來判斷兩個元素之間是否有關系的集合。
      它的基本思想為:對于兩個元素,如果他們之間有關系,則將其連接,以此形成一顆樹。
      對于任意兩個節點,如果它們有相同的根節點,則它們之間有關系。

      2. 建立步驟

      給定n個點,以及m個關系。

      1. 初始狀態

      將每個節點的根節點都指向自己

      for (int i = 0; i < n; i++) {
      	pre[i] = i;
      }
      

      2. 建立關系

      對于給定的兩個節點,我們發現,如果要連接兩個節點所在的樹,只能改變根節點。所以,我們先構建方法尋找根節點,再將一顆樹的根節點連接到另一棵樹的根節點上。

      int find(int x) {
      //1. 遞歸方式
      	return pre[x] == x ? x : find(pre[x])
      //2. 非遞歸
      	while(pre[x]^x) x = pre[x];
      	return x;
      }
      

      連接函數

      void merge(int x, int y) {
      	x = find(x), y = find(y);
      	pre[x] = y;
      }
      

      例題分析

      來源:洛谷P3367

      1. 并查集(無優化)

      #include <iostream>
      using namespace std;
      const int N = 10e5 + 9;
      int pre[N];
      int find(int x) {
      	while (pre[x] ^ x) x = pre[x];
      	return x;
      }
      void merge(int x, int y) {
      	x = find(x), y = find(y);
      	pre[x] = y;
      }
      void solve() {
      	int n, m;
      	cin >> n >> m;
      	for (int i = 0; i < N; i++) pre[i] = i;
      	while (m--) {
      		int z, x, y;
      		cin >> z >> x >> y;
      		if (z == 1) {
      			merge(x, y);
      		} else {
      			cout << (find(x) == find(y) ? 'Y' : 'N') << "\n";
      		}
      	}
      }
      int main() {
      	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
      	int _ = 1;
      	while (_--) solve();
      	return 0;
      }
      

      2. 路徑壓縮

      當我們每一次查找x的根節點的時候,順便將x的父節點的根節點也變成根節點,使得生成的樹的形狀又矮又胖。
      只需要修改find函數

      int find(int x) {
      	return pre[x] == x ? x : pre[x] = find(pre[x]);
      }
      

      或者為使用兩次while循環來改變。

      3. 按秩合并

      由上面的分析我們知道,如果是將一顆小樹附加到一顆大樹上面,那么在查找的過程中的復雜度會降低,以此,我們構建一個rank數組,初始值都為1,它記錄這棵樹的層數(只有根節點的數有效,畢竟我們只連接根節點)
      注意,當我們使用按秩合并的時候,我們在查找的時候就不能進行路徑壓縮(這樣會導致秩不斷在改變,我嘗試了一下一起使用,效果反而不如單個使用)。
      修改的merge函數為:

      void merge(int x, int y) {
      	x = find(x), y = find(y);
      	if (x == y) return;
      	if (rnk[x] >= rnk[y]) pre[y] = x, rnk[x]++;
      	else
      		pre[y] = x, rnk[y]++;
      }
      

      4. 按大小合并

      和秩一樣,當一顆較小的樹合并到另一棵較大的樹的時候,形成的樹會變得矮胖。因此,創建一個siz數組來儲存每棵樹的大小,初始值為1。和上面一樣,只需要修改為:

      void merge(int x, int y) {
      	x = find(x), y = find(y);
      	if (x == y) return;
      	if (siz[x] >= siz[y]) pre[y] = x, siz[x] += siz[y];
      	else
      		pre[y] = x, siz[y] += siz[x];
      }
      
      posted @ 2023-11-06 21:15  我沒有存錢罐  閱讀(89)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲精品国产男人的天堂| 中文在线天堂中文在线天堂| 亚洲婷婷六月的婷婷| 精品国产一区二区三区性色| 毛片亚洲AV无码精品国产午夜| 欧美精品一产区二产区| 亚洲 自拍 另类小说综合图区 | 一本色道久久综合无码人妻| 成人精品日韩专区在线观看 | 黑人av无码一区| 国精偷拍一区二区三区| 午夜福制92视频| 最新午夜男女福利片视频| 亚洲日韩国产精品第一页一区| 台山市| 好屌草这里只有精品| 国产免费午夜福利757| 免费无码高潮流白浆视频| 午夜夜福利一区二区三区| 中文字幕少妇人妻精品| 东京热一精品无码av| 国产综合色产在线视频欧美| 国产成人午夜福利院| 看全色黄大色黄大片 视频| 国产一区二区不卡91| 国产在线一区二区不卡| 苍溪县| 天天做天天爱夜夜夜爽毛片| 精品久久人人妻人人做精品| 亚洲免费一区二区av| 国产成人综合色就色综合| 日本免费一区二区三区日本| 精品999日本久久久影院| 成A人片亚洲日本久久| 无码熟妇人妻av在线电影| 国产播放91色在线观看| 精品一区二区不卡免费| 女人高潮流白浆视频| 精品视频在线观看免费观看| 国产熟睡乱子伦视频在线播放| 无码国产偷倩在线播放|