并查集 bnuoj51275 道路修建 Large

传送门:点击打开链接

题意:多次操作,操作1给两点之间增加一条边并求当前连通块数量,操作2求两点最早连通的时间,强制在线。

思路:q巨虐我千百遍

第一个思路想到可持久并查集+二分,因为很容易想到,然后只过了small的,large的T了

其实这题的思路比可持久并查集更简单。

并查集有两种方法来保持复杂度不退化,一种是路径压缩,一种是按照秩来做启发式合并,一般情况下我们都是写第一种

这里我们用第二种方法来合并,来保证树的形态不会被打乱。

每次查询两个点最早的连通时间,其实就是用最朴素的暴力方法,u和v都向上提找到LCA,然后LCA到u和LCA到v这两条链上的合并时间戳取最大值。

因为我们是按照启发式合并的,所以链长不会超过logn。

因为越靠近根节点的边越晚合并,所以只要看LCA连着的两条边的时间戳的最大值就够了。

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck(x) cout<<"["<<x<<"]"
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;
typedef pair<LL, int>PII;

const int MX = 1e6 + 5;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int n, m;
int deep[MX], P[MX];
int vis[MX], A[MX], z[MX];

int find(int x) {
    while(P[x] != x) x = P[x];
    return x;
}
bool Union(int i, int u, int v) {
    u = find(u), v = find(v);
    if(u == v) return false;
    if(deep[u] > deep[v]) swap(u, v);
    P[u] = v; A[u] = i;
    if(deep[u] == deep[v]) deep[v]++;
    return true;
}
int Query(int i, int u, int v) {
    vis[u] = i; z[u] = 0;
    for(; u != P[u]; u = P[u]) {
        vis[P[u]] = i;
        z[P[u]] = A[u];
    }
    if(vis[v] == i) return z[v];
    for(; v != P[v]; v = P[v]) {
        if(vis[P[v]] == i) return max(z[P[v]], A[v]);
    }
    return 0;
}

int main() {
    //FIN;
    int T; scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) {
            P[i] = i; deep[i] = 1;
            vis[i] = A[i] = z[i] = 0;
        }

        int ans = 0, tot = n, op, a, b;
        for(int i = 1; i <= m; i++) {
            scanf("%d%d%d", &op, &a, &b);
            a ^= ans; b ^= ans;
            if(op == 0) {
                if(Union(i, a, b)) tot--;
                ans = tot;
            } else ans = Query(i, a, b);
            printf("%d\n", ans);
        }
    }
    return 0;
}
    原文作者:道路修建问题
    原文地址: https://blog.csdn.net/qwb492859377/article/details/50638087
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞