Disjoint Set
Wu-Jun Pei
Problem
有N個人在不同的平行時空中,接下來有M對人,表示A、B存在在同一個時空,接下來有K對查詢A、B是否存在在同一個時空
Problem
嘗試1
把每條邊視為圖,DFS圖,把同樣的連通元件的節點都用相同的編號,之後每K次查詢就查詢兩個點是否擁有相同的編號。
複雜度:O( N + M ) + O( K )
Problem
嘗試1
時間複雜度:O( N + M ) + O( K )
空間複雜度:O( N + M )
看起來很好寫,其實真的很好寫 OuO
Problem
嘗試2
並查集(Disjoint Set / Union Find Tree):
是一個支援合併(併)以及查詢(查)的資料結構!
Disjoint Set
每節點有一個指標,指到他的父節點,可以用陣列來實作!
struct dsu{
int par[ maxn ];
};Disjoint Set
初始化:每一個節點原本都只到自己,意即每個節點都是一個獨立的集合。
複雜度:O( N )
struct dsu{
int par[ maxn ];
void init( int N ){
for( int i = 0; i < N; i++ ){
par[ i ] = i;
}
}
};Disjoint Set
查詢:遞迴地查詢父節點,直到找到根節點。
複雜度:O( N )
struct dsu{
int par[ maxn ];
...
int find( int x ){
return x == par[ x ] ? x : find( par[ x ] );
}
};Disjoint Set
合併:將兩個集合合併在一起,只要將B的根節點的父指標指到A即可。
複雜度:O( N ) 因為查詢要花很久的時間...
struct dsu{
int par[ maxn ];
...
void merge( int A, int B ){
par[ find( A ) ] = B;
}
};Disjoint Set
查詢是否在同一個時空:查詢是否有相同的父節點
複雜度:O( N )
struct dsu{
int par[ maxn ];
...
int same( int X, int Y ){
return find( X ) == find( Y );
}
};Disjoint Set
時間複雜度:
查詢:O( N )
合併:O( N )
空間複雜度:
O( N )
總複雜度是 O( MN ) + O( KN )
但其實,萬惡的根源就是在於查詢太久了啊QQ
Disjoint Set
小小的優化......路徑壓縮!
查詢:遞迴地查詢父節點,直到找到根節點,並更新。
均攤複雜度:O( logN )
struct dsu{
int par[ maxn ];
...
int find( int x ){
return par[ x ] = ( x == par[ x ] ? x : find( par[ x ] ) );
}
};Disjoint Set
此時的時間複雜度:
查詢:O( logN )
合併:O( logN )
總複雜度是 O( MlogN ) + O( KlogN )
這個時間點我們已經有足夠的能力完成這題了 > <
Disjoint Set, Even Faster!
每節點有一個指標和一個整數,指標指到他的父節點,整數表示集合的大小,也可以用陣列來實作!
struct dsu{
int par[ maxn ];
int siz[ maxn ];
};Disjoint Set, Even Faster!
合併:將兩個集合合併在一起,只要將B的根節點的父指標指到A即可。
使用啟發適合併,將小的合併到大的!
struct dsu{
int par[ maxn ];
...
void merge( int A, int B ){
int X = find( A ), Y = find( B );
if( siz[ X ] > siz[ Y ] )
swap( X, Y );
par[ X ] = Y;
siz[ Y ] += siz[ X ];
}
};Disjoint Set, Even Faster!
此時的時間複雜度是
O( ɑ(N+M, N) )
而 ɑ 可視為一個很小的常數
總複雜度是 O( ɑN )
我們更快了xD
Problem
有N個人在不同的平行時空中,接下來有K筆操作,表示:
- 一對人A、B在同一個時空
- 查詢A、B是否有機會認識
Problem
嘗試1
查詢:查詢兩個點是否擁有相同的編號。
合併:使用啟發式合併,將小的圖跟大的圖合併,每次改變小的圖的每個點的編號。
總複雜度 O( K( 1 + logN ) )
但是...感覺還蠻難實作的
Problem
嘗試2
使用 Disjoint Set 可以不用改 code 再 AC 一題!
Disjoint Set
By Wu-Jun Pei
Disjoint Set
- 26