ACM練級日誌 帶權並查集與食物鏈

2021-06-23 03:48:49 字數 1362 閱讀 9937

最近終於乾掉了高中兩年都沒有搞定的題目:食物鏈,就是那個a吃b,b吃c,c吃a這道noi的經典題。當年自己寫了200多行,把自己都寫碎了,也沒弄出來,最近學習了帶權並查集,終於搞定了這道題。

首先說說並查集為什麼能帶權值……  原先,最基本的並查集是維護等價關係了,如果a跟b處於同一集合,那說明a和b就是等價的。但是如果給並查集每個邊復上權值的話,那麼並查集就不光能表示等價關係,而且只要是「有關係」,就能表示。

當時我見到了這麼一道題:我有變數a到z,每次我會告訴你兩個變數的差(a-c=3 , r-s=2),然後途中我也會提問兩個變數的差是多少,你要回答我「是多少」,或者「不確定」。這裡我們就可以用帶權並查集:如果兩個變數之間已經「有關係」,那麼就合併入乙個集合,每個元素和它父親的邊權值就是這個差值。例如我們會有a->c =3, r->s=2,如果又有c->r=1,則沿著這條路走下去,就有了a->s=6。我們成功地維護了乙個表示「有關係」的並查集,同時我們還用邊的權值維護了這個關係是什麼。

不妨再看看noip的關押罪犯,簡化來講,關鍵一步就是每次給你兩個數a,b,告訴你a,b必須不能在乙個監獄裡,問你是否可行。那麼,對於這樣的關係,我們可以有a->b=1表示a和b不在一起,0表示在一起,然後邊的權值都要模2.這樣,如果a->b=1, b->c=1,則a->c=0,這個時候如果我告訴你a->c=1,就肯定沒戲了。

食物鏈的解題報告有很多,我覺得最好的解法就是帶權並查集,上面那個關押罪犯搞明白了,這種問題就都不是問題了。唯一值得注意的是,我在很多地方看到在維護權值的時候,作者用的都是找規律的辦法,其實用向量的思想去想會非常簡明而且絕不會出錯。舉個例子,最難的一步「合併」,假設我們合併x1, x2, x1的祖宗叫px1, x2的祖宗叫px2,我們在進行find(x1),find(x2)操作以後,就知道了x1->px1 = value[x1],x2->px2 = value[x2], 同時我們想新增的關係就是x1->x2 = d,現在關鍵問題是我們要知道px1 -> px2應該是多少(假設把x1並到x2去),那麼根據向量的思想,很容易我們就得出,px1 -> px2 = px1->x1 + x1->x2 + x2->px2 = -value[x1] + d + value[x2] ,需要的話再取模即可。

(注意!! 在對m取模之前,一定要加上m,不然如果d=value[x2]=0,你就死定了,1小時人生換來的教訓,食物鏈標程裡面有,但是當時我沒注意,付出代價了……  一定一定寫成 (-value[x1] + d + value[x2] + m)%m 。 )

同樣的,find的時候,我們假設要find(x1),x1當前的父親是px1, 我們用乙個p_old來代表px1,假設新的父親是p_new,我們想知道x1->p_new是多少。已知的是x1->p_old, 而p_old->p_new 在遞迴的時候已經更新了,所以我們發現把這兩個向量加起來就是x1->p_new,就可以很歡快地維護權值了。

食物鏈(並查集 帶權並查集與並查集

動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y是同類。第二種說法是 2 x ...

並查集 食物鏈(帶權並查集)

題目鏈結 題意 動物王國中有三類動物a,b,c,這三類動物的食物鏈構成了有趣的環形。a b吃c,c吃a。現有n個動物,以1 n編號。每個動物都是a,b,c中的一種,但是我們並不知道它到底是哪一種。有人用兩種說法對這n個動物所構成的食物鏈關係進行描述 第一種說法是 1 x y 表示x和y是同類。第二種...

食物鏈 帶權並查集

食物鏈 d x 維護的是跟根節點的距離 如果x,y在同乙個集合中,然後通過兩個根節點的距離就可以知道兩個之間的關係 d x 可以為負數,如果為負數的話,是反向轉食物鏈 例如 y距離根節點為 1 x距離根節點為 5 則 1 5 1mod3 0 所以y吃x 畫圖的話需要反向轉圈 如果 x y 為同類 則...