種類並查集的經典題
**飄過的小牛
:
關係域更新:
當然,這道題理解到這裡思路已經基本明確了,剩下的就是如何實現,在實現過程中,我們發現,更新關係域是乙個很頭疼的操作,網上各種分析都有,但是都是直接給出個公式,至於怎麼推出來的都是一筆帶過,讓我著實頭疼了很久,經過不斷的看discuss,終於明白了更新操作是通過什麼來實現的。下面講解一下
仔細再想想,rootx-x
、x-y
、y-rooty
,是不是很像向量形式
?於是我們可以大膽的從向量入手:
tx ty
x ~ y
對於集合裡的任意兩個元素x,y
而言,它們之間必定存在著某種聯絡,因為並查集中的元素均是有聯絡的(這點是並查集的實質,要深刻理解),否則也不會被合併到當前集合中。
那麼我們就把這2
個元素之間的關係量轉化為乙個
偏移量(大牛不愧為大牛!~ym
)。 由上面可知:
x->y 偏移量0時
x和y同類
x->y 偏移量1時
x被y吃
x->y 偏移量2時
x吃y 有了這個假設,我們就可以在並查集中完成任意兩個元素之間的關係轉換了。
不妨繼續假設,x
的當前集合根節點
rootx,y
的當前集合根節點
rooty
,x->y
的偏移值為d-1(題中給出的詢問已知條件)
(1)如果
rootx
和rooty
不相同,那麼我們把
rooty
合併到rootx
上,並且更新
relation
關係域的值(
注意:p[i].relation表示i
的根結點到
i的偏移量!!!!(向量方向性一定不能搞錯)
)此時 rootx->rooty = rootx->x + x->y + y->rooty
,這一步就是大牛獨創的
向量思維模式
上式進一步轉化為:rootx->rooty = (relation[x]+d-1+3-relation[y])%3 = relation[rooty]
,(模3
是保證偏移量取值始終在
[0,2]
間) (2)如果
rootx
和rooty相同(
即x和y
在已經在乙個集合中,不需要合併操作了,根結點相同
),那麼我們就驗證
x->y
之間的偏移量是否與題中給出的
d-1一致
此時 x->y = x->rootx + rootx->y
上式進一步轉化為:x->y = (3-relation[x]+relation[y])%3
,若一致則為真,否則為假。
#includeusing namespace std;
#define maxn 50005
int f[maxn],group[maxn];
int n,m;
void init()
} int find(int x)
int merge(int d,int x,int y)
else
}int main()
printf("%d\n",ans);
return 0;
}
POJ 食物鏈 種類並查集
time limit 1000ms memory limit 10000k 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係...
POJ食物鏈(經典種類並查集)
食物鏈 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a吃b,b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y是同類。第二種說法...
食物鏈 種類並查集
推薦blog傳送門,超級詳細 做題思路 種類並查集,首先利用乙個陣列a來確定並查集關係,同時在建立乙個陣列b來表示某點與他們的boss點 根點 的關係。現規定 0 某點與他的根點為同類 1 某點與他的根點的關係為,根點種類的動物的可以吃掉該點種類的動物 2 某點與他的根點的關係為,該點種類的動物的可...