【題解】 codevs1074 洛谷2024 食物鏈 詳述 《高級數據結構》-林厚從

還是放個鏈接


題解

一坨廢話

寫這題是因爲看着說是帶權並查集,然後想想當初第一次學並查集的時候考試上似乎也碰上一個帶權並查集然後被我難得的手推A掉了,就來試試這題看看我的假腦子會不會忘掉曾經會做的模型。
首先,開頭的ABC有什麼存在的意義啊(這樣說造成的後果在後面)!然後…這根本不是我認識的帶權並查集啊喂!不應該是根據權值的優先級來合併的那種麼(雖然是什麼題我也忘了)
看着像是要維護一個友好關係和敵對關係,這不是2-SAT麼,但我不會打呀!先手推一下…好複雜的樣子還是看dalaoKB博客吧,順便提高一下2-SAT的姿勢水平。

正式開始

… ……….. ……………….. (看着博客,沉默,拍頭)
這就是它帶的權啊,ABC是有用的啊
首先因爲動物總共只有三種(從這裏就開始錯了),還是可以用一種方式表示的(被吃就看作吃兩次,因爲總共就三種)所以關係只有三種。
然後我們知道,如果我們知道a和b的關係,b和c的關係,那麼我們就一定知道a和c的關係。這就是用並查集維護的原因啦。
那麼我們將兩個點之間(a與b),a和b同類爲0,a吃b看作1,b被a吃就看作2*(我知道網上其他博客都是a被b吃看作1的,但我中文思維嚴重,一定要這樣…)*
啥?你問我這個時候我們也知道了b和c的關係,具體怎麼知道a和c的關係?加起來取模3啊,就行了。畫個蛇咬尾式的圖就知道了
那麼我們的工作就是,在處理命令的時候若a與c都關於一個共同的b有關,那麼就判錯
1的時候a和c(與b的關係值,即上面的權值)是不是確實模3相等啊
2的時候a和c是不是確實是a吃c(a的關係值加一模三是否與c與b的關係值相等)而不是其它兩種情況呢 因爲我自己被這些加粗坑了
並沒有共同b的時候,先將祖先處理,再根據應滿足的關係式移項賦值,這個地方可能會有人像我一樣有個假腦子,看着別人的賦值一下子不知道怎麼回事吧
接下來默認a接到c下面
1的時候要求a和c要是同類那麼就是 a到c的祖先的總權值(總權值即a到祖先的總權值加上a的祖先到c的祖先的總權值 記得模三)要等於c到祖先的權值 (此時c的祖先就是對於a和c來說的b了)。用dx表示x到祖先的權值,用式子表示爲

droot_of_a+da=dc
那麼
droot_of_a=dcda
這樣賦值
具體實現需要注意小於零的情況
2的時候 根據我的中文思維式子就和大部分不一樣了,類比也可得出

代碼

#include <cstdio>
const int maxn = 5e4 + 10;
int f[maxn], d[maxn];
int Find(int x){
    if (f[x] == x) return x;
    int fa = f[x];
    f[x] = Find(f[x]); d[x] = (d[fa] + d[x]) % 3;
    return f[x];
}
int main (){
    int n, k; scanf ("%d%d", &n, &k);
    for (int i = 1; i <= n; ++i) f[i] = i;
    int ans = 0;
    for (int i = 1, fl, X, Y, rx, ry; i <= k; ++i){
    scanf ("%d%d%d", &fl, &X, &Y);
    if (X > n || Y > n){++ans; continue;}
    if (X == Y){if (fl == 2) ++ans; continue;}
    rx = Find(X), ry = Find(Y);
    if (rx == ry){
        if (fl == 1 && d[X] != d[Y]) ++ans;
        if (fl == 2 && (d[X] + 1) % 3 != d[Y]) ++ans;
    }
    else{
        f[rx] = ry;
        if (fl == 1) d[rx] = (d[Y] - d[X] + 3) % 3;
        else d[rx] = (d[Y] - d[X] + 2) % 3;
    }
    }
    printf ("%d", ans);

    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章