zoukankan      html  css  js  c++  java
  • 连通

    题目描述

    给出一张n个点,0条边的图,在第i个时刻(下标从1开始),向图中加入第i条无向边。

    有q次询问,每次询问u,v两个点最早在什么时刻连通。

    输入

    输出

    样例输入

    4 6
    1 3
    3 4
    1 4
    2 4
    2 3
    1 2
    4
    1 2
    3 4
    1 4
    2 3

    样例输出

    4
    2
    2
    4

    提示

    解题思路

    看到题目的第一感觉,发现数据是出奇地大,但这一道题目,肯定是可以构图的。(关键我连构图这一节都分析了好久才想到,而且还放弃并查集用了最短路)。事实上,此题就是需要并查集与LCA,图中的边很多,我们利用并查集其实也可以消去一些没有用的边,最后只可能有N-1条有效边,大大减小了时间复杂度。最后问连通没有,我们仅仅需要求出这一一段树上路径的最短路。

    我们处理并查集时,用秩优化,这里特别注意,不要用路径压缩,路径压缩可以说是把树全部打乱了,对我们来说这是致命的,我们用秩优化,因而树就是一棵长度为logn的树。

    但树其实是经过并查集处理,是很奇怪的,我们可以找到根节点,再进行dfs,真正构造出一棵树。求到深度,距离。

    构造完之后,就很水了,可以暴力求树上最大路径,还可以倍增,速度似乎要快一点。

    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    struct edge{
        int u,v;
        edge(){};
        edge(int U,int V){
            u = U,v = V;
        }
    };
    int n,m,fa[50005],rank1[50005],q,mov[50005],dis[50005];
    vector <edge>G[50005];
      
    void makeset(int x){
        for (int i = 1;i <= x; i ++){
            fa[i] = i;
            rank1[i] = 1;
        }
    }
      
    int findset(int x){
        while (x != fa[x])
            x = fa[x];
        return x;
    }
      
    void unionset(int a,int b,int time){
        int t = findset(a);
        int t1 = findset(b);
        if (t == t1)
            return ;
        G[t].push_back(edge(t1,time));
        G[t1].push_back(edge(t,time));
        if (rank1[t] > rank1[t1])
            fa[t1] = t;
        else {
            fa[t] = t1;
            if (rank1[t] == rank1[t1])
                rank1[t1] ++;
        }
    }
      
    void dfs(int step){
        int x = G[step].size();
        for (int i = 0;i < x; i ++){
            if (!mov[G[step][i].u]){
                mov[G[step][i].u] = 1;
                rank1[G[step][i].u] = rank1[step] + 1;
                dis[G[step][i].u] = G[step][i].v;
                dfs(G[step][i].u);
            }
        }
    }
      
    int lca(int u,int v){
        int ans = 0;
        while (rank1[u] > rank1[v]){
            ans = max(dis[u],ans);
            u = fa[u];
        }
        while (rank1[v] > rank1[u]){
            ans = max(dis[v],ans);
            v = fa[v];
        }
        while (u != v){
            ans = max(dis[u],ans);
            u = fa[u];
            ans = max(dis[v],ans);
            v = fa[v];
        }
        return ans;
    }
      
    int main(){
        scanf ("%d%d",&n,&m);
        makeset(n);
        for (int i = 1 ;i <= m;i ++){
            int a,b;
            scanf ("%d%d",&a,&b);
            unionset(a,b,i);
        }
        for (int i = 1;i <= n;i ++){
            if (fa[i] == i){
                mov[i] = 1;
                rank1[i] = 1;
                dfs(i);
            }
        }
        scanf ("%d",&q);
        while (q --){
            int a,b;
            scanf ("%d%d",&a,&b);
            if (findset(a) != findset(b))
                printf("-1
    ");
            else if (a == b)
                printf("0
    ");
            else  
                printf("%d
    ",lca(a,b));
        }
    }

    总结

    我表示这道题考试时候是摸到了一点思路的,但确实是没想到树,构造这一棵树才是最为关键的。树构造出来,之后的答案就可以很好很轻松地做了。

  • 相关阅读:
    RTSP协议转RTMP协议的行业视频接入网关EasyRTSPLive如何实现音频转码的
    RTSP协议转RTMP协议的行业视频接入网关EasyRTSPLive之跨平台ini配置及通道的方法
    GB/T28181协议EasyGBS播放1080p视频直播会花屏
    国标GB/T28181协议下播放器起播慢或者延迟高如何解决?
    EasyGBS查找大华设备的录像列表时失败
    ffmpeg增加h264编解码功能模块方法
    EasyNVR控制台运行出现invalid license关于计算机保护软件类似于360、腾讯云管家等限制相关问题
    摄像机经过多级路由转换无法被EasyNVR拉流问题处理方法
    使用EasyNVR软件对接海康摄像头对接失败问题解析
    GB/T28181协议使用EasyNVR降低播放延迟方法
  • 原文地址:https://www.cnblogs.com/lover-fucker/p/13566688.html
Copyright © 2011-2022 走看看