題意:
與吃瓜題1題意一致,只是西瓜的種類從兩種變成了無數種。
題解:
在吃瓜題1裡,由於只有兩類西瓜,因此我們可以使用分類的方法來表示異同。而在這題中,由於種類數無窮,我們只有記錄每個節點的對立節點,在詢問x與y的關係時,我們查詢x的對立節點集合中是否出現y節點。
那麼如何記錄對立節點集呢?我們採用set
當兩個節點確定異種的時候,我們分別在set[x]和set[y]中新增y和x
當兩個節點確定同種的時候,我們將他們的set合併到一起。合併是要注重技巧的!每次,我們選擇較小的set,新增到較大的set中。因此,最壞情況其實就類似於乙個二叉樹的合併次數,大約為n次。
#include
#include
using
namespace
std;
const
int maxn = 1e6 + 5;
int pre[maxn];
setdiff[maxn];
int findset(int x)
void unionset(int x,int y)
}else
}}int main()
while(m--)
else
}else
}return
0;}
吃瓜題2(虛擬分類並查集 啟發式合併)
題意 與吃瓜題1題意一致,只是西瓜的種類從兩種變成了無數種。題解 在吃瓜題1裡,由於只有兩類西瓜,因此我們可以使用分類的方法來表示異同。而在這題中,由於種類數無窮,我們只有記錄每個節點的對立節點,在詢問x與y的關係時,我們查詢x的對立節點集合中是否出現y節點。那麼如何記錄對立節點集呢?我們採用set...
並查集的啟發式合併
在原來剛接觸並查集的時候,感覺確實很方便,也是認為並查集就那麼點東西,簡單方便,但是後來無意間發現了乙個並查集的啟發式合併,可以對並查集進行優化,它優化的理論是用乙個陣列來記錄每個節點的深度,每一次合併都把節點向深度 高度 大的節點上進行合併,從而對最後的 生成樹 深度進行了優化。受益匪淺,好長時間...
並查集 啟發式合併,路徑壓縮
一直沒想過自己寫的並查集的複雜度 看那一行 還挺竊喜 貼一下正版的啟發式合併,這樣複雜度就真正到了反阿克曼函式那什麼balabala 乙個優化是 把小的樹合併到大樹中,這樣會讓深度不太大。這個優化稱為啟發式合併。乙個優化是把沿途上所有結點的父親改成根。這一步是順便的,不增加時間複雜度,卻使得今後的操...