[codeforces] Gym

来源:互联网 发布:软件行业税收优惠政策 编辑:程序博客网 时间:2024/05/17 08:55

[codeforces] Gym - 100814C Connecting Graph (并查集+LCA)

题目链接:100814C Connecting Graph
题目大意:
给定n个点, m个操作, 操作由两种形式
1uvu,v 连一条边
2uv 询问u,v最早什么时候连通, 如果不连通输出1
数据范围:
(1<=n,m<=1e5)

解题思路:
两个点什么时候最早连通就是这两个点之间的最大值, 可以想到用LCA+倍增维护最大值。 题中并没有说肯定是棵树, 但是如果两个点之前已经联通了, 当前这条边就没有必要加进去了(有点最小生成树的感觉), 所以最后肯定生成的是一个树。
这道题的主要思想就是用LCA + 倍增维护最大值。

代码:

/********************************************** *Author*        :ZZZZone *reated Time*  : 2017/8/8 20:57:14 *ended  Time*  : 2017/8/9 12:05:21*********************************************/#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <string>#include <cmath>#include <cstdlib>#include <ctime>#include <stack>using namespace std;typedef pair<int, int> PII;typedef long long LL;typedef unsigned long long ULL;const int MaxN = 1e5;int fa[MaxN + 5], dis[MaxN + 5];int up[MaxN + 5][25], Max[MaxN + 5][25];vector<PII>edge[MaxN + 5];struct NODE{    int p, u, v;}q[MaxN + 5];int T, n, m, tot;void init(){    for(int i = 1; i<= n; i++) fa[i] = i;    memset(dis, 0, sizeof(dis));    memset(up, 0, sizeof(up));    memset(Max, 0, sizeof(Max));    memset(edge, 0, sizeof(edge));    tot = 0;}int find(int x){    if(fa[x] == x) return x;    else return fa[x] = find(fa[x]);}void Union(int u, int v){    int fu = find(u), fv = find(v);    if(fu != fv) fa[fu] = fv;}void dfs(int u){    /*    for(int i = 1; i <= 20; i++){        up[u][i] = up[up[u][i - 1]][i - 1];        Max[u][i] = max(Max[u][i - 1], Max[up[u][i - 1]][i - 1]);    }    */    for(int i = 0; i < edge[u].size(); i++){        int v = edge[u][i].first;        int len = edge[u][i].second;        if(dis[v] == 0){            dis[v] = dis[u] + 1;            Max[v][0] = len;            up[v][0] = u;            dfs(v);        }    }}void init_lca(){    for(int j = 1; (1 << j) <= n; j++){        for(int i = 1; i <= n; i++){            up[i][j] = up[up[i][j - 1]][j - 1];            Max[i][j] = max(Max[i][j - 1], Max[up[i][j - 1]][j - 1]);        }    }}int getans(int a, int b){    if(dis[a] < dis[b]) swap(a, b);    int c = dis[a] - dis[b], res = 0;    for(int i = 0; (1 << i) <= n; i++){        if(c & (1 << i)){            res = max(res, Max[a][i]);            a = up[a][i];        }    }    if(a == b) return res;    for(int i = 20; i >= 0; i--){        if(up[a][i] != up[b][i]){            res = max(res, Max[a][i]);            res = max(res, Max[b][i]);            a = up[a][i];            b = up[b][i];        }    }    return max(res, max(Max[a][0], Max[b][0]));}int main(){    scanf("%d", &T);    while(T--){        scanf("%d %d", &n, &m);        init();        for(int i = 1; i <= m; i++){            int x, u, v;            scanf("%d %d %d", &x, &u, &v);            if(x == 1){                int fu = find(u), fv = find(v);                if(fu == fv) continue;                fa[fu] = fv;                edge[u].push_back(make_pair(v, i));                edge[v].push_back(make_pair(u, i));            }            else q[++tot].p = i, q[tot].u = u, q[tot].v = v;        }        for(int i  = 1; i <= n; i++)            if(dis[i] == 0){                dis[i] = 1;                dfs(i);            }        init_lca();        for(int i = 1; i<= tot; i++){            int fu = find(q[i].u), fv = find(q[i].v);            if(fu != fv) printf("-1\n");            else {                int ans = getans(q[i].u, q[i].v);                if(ans > q[i].p) printf("-1\n");                else printf("%d\n", ans);            }        }    }    return 0;}

在此输入正文

原创粉丝点击