Gym 100814C Connecting Graph 并查集+LCA

Description

standard input/output 
Statements

Alex is known to be very clever, but Walter does not believe that. In order to test Alex, he invented a new game. He gave Alex nnodes, and a list of queries. Walter then gives Alex one query every second, there are two types of queries:

 means: adding an undirected edge between nodes u and v.

 means: what was the earliest time (query index) when u and v became connected? 2 nodes are connected if there is a path of edges between them. Alex can solve this problem easily, but he is too busy now, so he is asking for your help.

Input

The first line contains an integer T, the number of test cases. Each test case begins with a line containing two integers (1 ≤ n, m ≤ 105), the number of nodes and queries, respectively. Then there are m lines, each line represents a query and contains three integers,typeu and v ( , 1 ≤ u, v ≤ n)

Output

For each query of type 2, print one line with one integer, the answer to the query. If the 2 nodes in the query are not connected, print -1.

Sample Input

Input
1
4 5
1 1 2
2 1 2
1 2 3
2 1 3
2 1 4
Output
1
3
-1

Hint

Warning: large Input/Output data, be careful with certain languages.

 

2016寒假训练04C,赛后补的:题意是给出m中操作,分别是1, u, v,既节点u,v之间连一条边,2, u, v即询问是最早是第几次操作使得u,v联通

可以用并查集维护连通性,如果(u, v)已经联通,那么对于操作1,(u,v)就不再连边,这样对于每一个联通块得到的是一颗树,所有的联通块对应于森林

维护mx[u][i]表示节点u到其第2^i个祖先之间边权的最大值,这样在查询lca的时候就能得到u, v之间路径的最大边权,就是对应于2的答案

复制代码
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
const int DEG = 20;
typedef pair<int, int> pii;
int head[N], tot;
struct Edge {
    int v, w, next;
    Edge() {}
    Edge(int v, int w, int next) : v(v), w(w), next(next) {}
}e[N << 1];
struct Query {
    int u, v, w;
    Query() {}
    Query(int u, int v, int w) : u(u), v(v), w(w) {}
}q[N];
int f[N][DEG + 1], mx[N][DEG + 1], fa[N], deg[N];
void init(int n) {
    for(int i = 1; i <= n; ++i) fa[i] = i;
    memset(head, -1, sizeof head);
    tot = 0;
}
void add(int u, int v, int w) {
    e[tot] = Edge(v, w, head[u]);
    head[u] = tot++;
}
int find(int x) {
    return fa[x] == x ?
    x : fa[x] = find(fa[x]);
}
void BFS(int rt) {
    queue<int> que;
    deg[rt] = 0;
    f[rt][0] = rt;
    mx[rt][0] = 0;
    que.push(rt);
    while(!que.empty()) {
        int u = que.front(); que.pop();
        for(int i = 1; i < DEG; ++i) {
            f[u][i] = f[f[u][i - 1]][i - 1];
            mx[u][i] = max(mx[u][i - 1], mx[f[u][i-1]][i-1]);
        }
        for(int i = head[u]; ~i; i = e[i].next) {
            int v = e[i].v;
            int w = e[i].w;
            if(v == f[u][0]) continue;
            deg[v] = deg[u] + 1;
            f[v][0] = u;
            mx[v][0] = w;
            que.push(v);
        }
    }
}
int getmx(int u, int v) {
    if(deg[u] > deg[v]) swap(u, v);
    int hu = deg[u], hv = deg[v];
    int tu = u, tv = v, res = 0;
    for(int det = hv - hu, i = 0; det; det >>= 1, ++i) {
        if(det & 1) { res = max(res, mx[tv][i]); tv = f[tv][i]; }
    }
    if(tu == tv) return res;
    for(int i = DEG - 1; i >= 0; --i)
    {
        if(f[tu][i] == f[tv][i]) continue;
        res = max(res, mx[tu][i]);
        res = max(res, mx[tv][i]);
        tu = f[tu][i];
        tv = f[tv][i];
    }
    return max(res, max(mx[tu][0], mx[tv][0]));
}
int main() {
    int _; scanf("%d", &_);
    while(_ --)
    {
        int n, m;
        scanf("%d%d", &n, &m);
        int u, v, t, num = 0, res;
        init(n);
        for(int i = 1; i <= m; ++i) {
            scanf("%d%d%d", &t, &u, &v);
            if(t == 1) {
                int fu = find(u);
                int fv = find(v);
                if(fu == fv) continue;
                fa[fu] = fv;
                add(u, v, i);
                add(v, u, i);
            }else {
                q[num++] = Query(u, v, i);
            }
        }
        for(int i = 1; i <= n; ++i) if(fa[i] == i) {
            BFS(i);
        }

        for(int i = 0; i < num; ++i) {
            if(q[i].u == q[i].v) puts("0");
            else {
                int fu = find(q[i].u);
                int fv = find(q[i].v);
                if(fu != fv) puts("-1");
                else {
                    res = getmx(q[i].u, q[i].v);
                    printf("%d\n", res > q[i].w ? -1 : res);
                }
            }
        }
    }
}
View Code
复制代码

 

posted @   JL_Zhou  阅读(574)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
历史上的今天:
2015-02-03 Rightmost Digit
点击右上角即可分享
微信分享提示