並查集有兩個擴充套件應用,乙個是帶邊權的並查集另乙個是帶擴充套件域的並查集。這道題用兩種方法都可以做。值得學習。
題目:奇偶遊戲
做法1:帶邊權的並查集
1、用 sum
[x
]sum[x]
sum[x]
表示 1
11到 x
xx 中1的個數(此處 sum
[x
]sum[x]
sum[x]
不需要具體求出),讀入「l,r
,rel
l,r,rel
l,r,re
l」,如果 rel
=odd
rel=odd
rel=od
d,那麼證明 sum
[l−1
]sum[l-1]
sum[l−
1]和 sum
[r
]sum[r]
sum[r]
奇偶性不同(字首和的思想),反之則相同。
2、有了這個操作,我們就可以把輸入資料當作 x1,
x2,.
..
x_1,x_2,...
x1,x2
,..
. 和他們奇偶性的關係,如果是奇偶性不同,兩個元素之間則連線一條邊權為 1 的邊反之為 0 。此時,記 d[x
]d[x]
d[x]
為 xx
x 到 p[x
]p[x]
p[x]
的奇偶性。同時,這些元素的關係具有傳遞性,可以相互推出,所以把可以推出的元素放在乙個集合裡,用並查集維護 d[x
]d[x]
d[x]
。3、接下來並查集維護時面臨兩個問題:
a)呼叫 find() 函式時子節點直接指向根節點過程中邊權的計算;
本質上就是亦或運算(xor
xorxo
r),因為相同出 0,不同出 1,即奇+奇=偶,偶+偶=偶,奇+偶=奇,這也與上面的定義正好一致。
b)合併兩顆樹時加的那一條邊的邊權的計算;(以 p[x
]=fi
nd(y
)p[x]=find(y)
p[x]=f
ind(
y)操作說明)
這裡不難看出公式 rel
(x,y
)=d[
x]
rel(x,y)=d[x]
rel(x,
y)=d
[x]xor
xorxord[
y]
d[y]
d[y]
x or
xorxord[
p[x]
]d[p[x]]
d[p[x]
],則可以得到新加的邊權計算公式為:d[p
[x]]
=d[x
]d[p[x]]=d[x]
d[p[x]
]=d[
x]x or
xorxord[
y]
d[y]
d[y]
x or
xorxorre
l(x,
y)
rel(x,y)
rel(x,
y).4、最後要注意離散化資料,這裡不要求保序性,所以用偷個懶用 map
mapma
p 好了。
**:
#include
#include
#include
#include
#include
using
namespace std;
const
int n=
10010
;unordered_map<
int,
int> mp;
int p[n*2]
,d[n*2]
;struct nodeq[n]
;int n,m,tot;
intdis
(int x)
intfind
(int x)
return p[x];}
intget
(char x)
intmain()
for(
int i=
1;i<=tot;i++
) p[i]
=i;for
(int i=
1;i<=m;i++
)else}}
cout
}
奇偶遊戲 帶權並查集
奇偶遊戲 首先需要知道異或這種東西 兩個數異或的結果是什麼 兩個數按位做差的絕對值 異或相當於 模2 做加法 只看最後一位 例如 5 101 3 011 只看最後以為為0 就是偶數,奇數加奇數為偶數,這一題用到此方法 1個數異或自己為0 乙個數異或0 還是自己 定義s i 為前i個數又多少個奇數1 ...
資料結構 並查集
並查集,顧名思義,合併 查詢 集合 並查集是一種樹型的資料結構,用於處理一些不相交集合 disjoint sets 的合併及查詢問題。常常在使用中以森林來表示。對於概念等等的這裡不再贅述,直接講解應用。應用1 判斷圖中有多少聯通分量 或者圖是否聯通 聯通分量 1 hdu 1213 應用2 判斷圖是否...
資料結構 並查集
time limit 1000ms memory limit 65536k 某城市有n個人,現在給定關於n個人的m條資訊,m條資訊是兩個人在同乙個小區,根據所給資訊,判斷這個城市最多可能有多少個小區。n個人編號為1 n。多組輸入。每組第一行有兩個整數n,m 2 n 50000,0 m n 2 接下來...