BZOJ4668: 冷戰 [並查集 按秩合併]

BZOJ4668: 冷戰

題意:php

給定 n 個點的圖。動態的往圖中加邊,而且詢問某兩個點最先什
麼時候聯通,強制在線。ios


還能夠這樣亂搞spa

並查集按秩合併的好處:code

  1. 深度不會超過\(O(\log n)\)
  2. 樹的結構保持較穩定 -> 雖然說連邊的時候依舊是祖先來連邊,但連邊不會改變原來的結構,而且(u,v)路徑上會通過新連的邊

因而就能夠亂搞了ci

維護一個按秩合併的並查集,給連邊操做加時間戳,查詢的時候暴力求路徑上時間戳最大值get

PS:暴力lca也是須要deepstring

PS2:按秩合併是看高度的吧,爲何個人好慢???人傻自帶大常數???而且改爲啓發式合併個人就T掉了it

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 5e5+5;

int n, m, fa[N], val[N], he[N], deep[N], tim, ans;
int find(int x) {
    if(x == fa[x]) return x;
    else {
        int f = find(fa[x]);
        deep[x] = deep[fa[x]] + 1;
        return f;
    }
}
void Union(int x, int y) {
    tim++;
    x = find(x); y = find(y);
    if(x == y) return;
    if(he[x] < he[y]) swap(x, y);
    fa[y] = x;
    val[y] = tim;
    he[x] = max(he[x], he[y]+1);
}
void Find(int x, int y) {
    int fx = find(x), fy = find(y);
    ans = 0;
    if(fx != fy) cout << ans << '\n';
    else {
        while(x != y) {
            if(deep[x] < deep[y]) swap(x, y);
            ans = max(ans, val[x]); x = fa[x];
        }
        cout << ans << '\n';
    }
}
int main() {
    freopen("in", "r", stdin);
    ios::sync_with_stdio(false); cin.tie(); cout.tie();
    cin >> n >> m;
    for(int i=1; i<=n; i++) fa[i] = i;
    for(int i=1; i<=m; i++) {
        int c, x, y;
        cin >> c >> x >> y;
        x ^= ans; y ^= ans; //printf("hi %d %d %d\n", c, x, y);
        if(c == 0) Union(x, y);
        else Find(x, y);
    }
}
相關文章
相關標籤/搜索