南昌理工acm
並查集屬於半模板資料結構
可以有很多種維護方式(後面我會舉幾個,我剛學一些,也不是很懂,萌新磕頭)
先說並查集怎麼用
for
(int i=
1;i<=n;i++
) p[i]
=i;///初始化,就是這麼簡單
再講合併之前我們要講一下路徑壓縮
如圖,就是將所以的點全部連到了他的最上面的節點,主要是為了減少查詢時間(高效)
**如下
int
find
(int x)
這就是俗稱找爸爸函式(字面意思)
合併兩個集合,很容易,只要把他的祖宗節點並到另乙個集合就行
查詢兩個集合,就是看看他們有沒有在乙個集合裡,就行。
int
find
(int x)
p[find
(a)]
=find
(b);
//合併集合if(
find
(a)==
find
(b))
puts
("yes");
//查詢集合
else
puts
("no"
);
這些就是整個並查集的核心(但這不是全部,這是半模板的資料結構)
剩下的主要靠你自己維護(下面介紹幾個比較好的並查集型別)
這裡先練一道模板題
**如下
#include
#include
using namespace std;
const
int n=
2e5+10;
int p[n]
;int n,m;
intfind
(int x)
intmain()
}return0;
}
- 並查集主要維護 有三
1 數量
2 種類
3 權重
在學習這三種之前我們看一道(關於反集思想的並查集,來感受一下並查集的魅力)反集主要應用 就一句話
敵人的敵人就是朋友(夥伴們來題)
超經典 點開看看吧
**如下
大家在紙上畫一下就明白了
通過交替的反集思想來解決問題
是不是感覺到並查集 的強大
反正我是對這個東西,佩服的五體投地,**的太慘 /(ㄒoㄒ)/~~
這裡我推薦acwing這道新手題
**如下
#include
using namespace std;
const
int n=
1e5+10;
int p[n]
,sz[n]
;int n,m,a,b;
string str;
void
init()
}int
find
(int x)
void
merge
(int a,
int b)
intmain()
else
if(str==
"q1"
)else
}return0;
}
這裡主要是維護根節點的大小,不進行子節點不需要維護
所以只需要更新根節點的sz陣列就行了(size打不出來,就用sz了)
這種題型也比較常見,無非是換了一種寫法,相信大家可以認真對待
難搞的並查集來了
這裡我們一起講
用最經典的食物鏈吧,方便理解
食物鏈題目
這裡先上**
#include
using namespace std;
const
int n=
5e4+10;
int p[n*3]
;int n,m,ans;
intfind
(int x)
intmain()
}else}}
cout<
return0;
}
#include
#include
using namespace std;
const
int n=
5e4+10;
int p[n]
,r[n]
;int n,m,ans;
intfind
(int x)
return p[x];}
intmain()
else}}
cout<
return0;
}
這裡我給出兩種方法的詳解
這裡,詳細的講解了加權並查集
秦大佬 的講解 我覺得最好 關於擴充套件域並查集
再補充一道題,也很經典(加權並查集)
[noi2002]銀河英雄傳說 加權並查集
#include
#include
#include
#include
using namespace std;
const
int n=
1e6+10;
int p[n]
,sz[n]
,d[n]
;int n;
void
init()
intfind
(int x)
return p[x];}
intmain()
}else
}return0;
}
簡單題 這裡我用的是trie樹+並查集
#include
#include
using namespace std;
const
int n=
2e5+10;
int p[n]
;int son[n][58
],cut[n]
,idx;
int n,m;
intfind
(int x)
void
insert
(string a,
int k)
cut[p]
=k;}
intquery
(string a)
return cut[p];}
intmain()
for(
;m;m--
) cin>>n;
for(
;n;n--
)return0;
}
這是我的小小總結,希望大家能多多加油
萌新的我,才剛剛接觸**不久,路是那麼那麼遠
想想就傷心 ,演算法沒有盡頭啊
哭泣/(ㄒoㄒ)/~~
支援我一下下吧,希望得到大家的點讚
製作不易,謝謝大家
詳解 並查集高階技巧 加權並查集 擴充套件域並查集
可以理解為使用陣列實現的樹形結構,只儲存了每個節點的父節點 前驅 功能為 合併兩個節點 及其所在集合 查詢節點所屬集合的代表節點 可以理解為根節點 以6個元素為例 編號0到5 把0單獨劃分為乙個集合 把1,2,3,4劃分為乙個集合 把5單獨劃分為乙個集合。n個元素的並查集,只需要乙個容量為n的陣列f...
並查集的擴充套件域
核心思想 fa a 儲存與a同類的 fa a 1 n 儲存與a發生第一類關係的 fa a 2 n 儲存與a發生第二類關係的 fa a 3 n 儲存與a發生第三類關係的 分析將並查集中儲存節點關係的f陣列擴大2倍,1 n表示朋友,n 1 2 n表示敵人。那麼對於x,y,如果x和y是朋友,直接合併,如果...
True Liars 擴充套件域並查集
傳送門 每個點拆成兩個,表示好人或壞人 我們合併集合後,發現存在幾組對立的集合 也就是說這個集合和與它對立的集合只能選乙個 我們用rt1 i rt2 i 表示第i個集合 和 與第i個集合對立的集合 cnt1,cnt2表示該集合好人的個數 用f i j 表示到第i個集合,好人為j的方案數 同時記錄fr...