GYM

题意:

  初始有n个点,m次操作。每次操作加一条边或者询问两个点第一次连通的时刻(若不连通输出-1)。

题解:

  用并查集维护每个点所在连通块的根。对于每次加边,暴力的更新新的根。

  每次将2个块合并时,将小的块并向大的块。这么合并使得每个点的根最多更新log2n次,并储存每次更新信息(更新时刻以及新的根)。

  对于每一次询问,二分两个点第一次连通的时刻。对于每一个二分的时刻,求的是两点的根是否相同。

  由于存储过了每个点根的更新信息,所以再用二分求出他这个时刻的根。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+10;
int t;
int n, m;
int u, v, k;
int f[N], num[N];
vector<pair<int, int> > g[N];
vector<int> c[N];
bool check(int x) {
    int l = 0, r = g[u].size()-1;
    while(l <= r) {
        int mid = l+r>>1;
        if(g[u][mid].first <= x) l = mid+1;
        else r = mid-1;
    }
    int p1 = g[u][r].second;
    l = 0, r = g[v].size()-1;
    while(l <= r) {
        int mid = l+r>>1;
        if(g[v][mid].first <= x) l = mid+1;
        else r = mid-1;
    }
    int p2 = g[v][r].second;
    if(p1==p2) return 1;
    return 0;
}
int main() {
    scanf("%d", &t);
    while(t--) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) {
            num[i] = 1;
            f[i] = i;
            c[i].clear();
            g[i].clear();
            c[i].push_back(i);
            g[i].push_back(make_pair(0, i));
        }
        for(int i = 1; i <= m; i++) {
            scanf("%d%d%d", &k, &u, &v);
            if(k&1) {
                u = f[u]; v = f[v];
                if(u!=v) {
                    if(num[u]>num[v]) swap(u, v);
                    for(int j = 0; j < num[u]; j++) {
                        c[v].push_back(c[u][j]);
                        f[c[u][j]] = v;
                        g[c[u][j]].push_back(make_pair(i, v));
                    }
                    num[v] += num[u];
                    num[u] = 0;
                    c[u].clear();
                }
            }
            else {
                int l = 0, r = i-1;
                while(l<=r) {
                    int mid = l+r>>1;
                    if(check(mid)) r = mid-1;
                    else l = mid+1;
                }
                if(check(r+1)) printf("%d
", r+1);
                else puts("-1");
            }
        }
    }    
}
View Code
原文地址:https://www.cnblogs.com/Pneuis/p/9130170.html