zoukankan      html  css  js  c++  java
  • [2020多校联考]小Y的图

    2020.11.21

    解法

    连接两个点的那条最大值最小的路径一定在最小生成树上,而又要查询这个最大值是多少,那么就想到建出克鲁斯卡尔重构树。由于可能不连通,所以最后建出来的实际上是重构森林,记得要把每个连通块都遍历到。

    对于节点的连通性,直接用之前维护好的并查集就好了,不连通就输出-1,连通的话再在重构树内倍增找LCA,最后输出LCA的权值(该节点所表示的边的边权)。

    #include<stdio.h>
    #include<algorithm>
    using namespace std;
    #define N 300007
     
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
     
    struct E{
        int next,to;
    }e[N<<2];
    struct E_{
        int u,v,dis;
        E_(int u=0,int v=0,int dis=0):u(u),v(v),dis(dis){}
        bool operator <(const E_ x) const{
            return dis<x.dis;
        }
    }L[N];
    int n,m,Q,fa[N<<1],f[N<<1][20],val[N<<1],head[N<<1],cnt=0,dep[N<<1];
     
    inline int find(int x){
        if(fa[x]==x) return x;
        return fa[x]=find(fa[x]);
    }
     
    inline void add(int id,int to){
        e[++cnt]=(E){head[id],to};
        head[id]=cnt;
    }
     
    bool vis[N<<1],tag[N<<1];
    void dfs(int u){
        for(int i=1;i<20;i++)
            f[u][i]=f[f[u][i-1]][i-1];
        for(int i=head[u];i;i=e[i].next){
            int v=e[i].to;
            if(vis[v]) continue;
            dep[v]=dep[u]+1,vis[v]=1;
            dfs(v);
        }
    }
     
    inline void swap(int &x,int &y){x^=y,y^=x,x^=y;}
    inline int Lca(int u,int v){
        if(dep[u]<dep[v]) swap(u,v);
        for(int i=19;~i;i--)
            if(dep[f[u][i]]>=dep[v])
                u=f[u][i];
        if(u==v) return u;
        for(int i=19;~i;i--)
            if(f[u][i]!=f[v][i])
                u=f[u][i],v=f[v][i];
        return f[u][0];
    }
     
    int main(){
    //  freopen("graph.in","r",stdin);
    //  freopen("graph.out","w",stdout);
        n=read(),m=read(),Q=read();
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++)
            L[i].u=read(),L[i].v=read(),L[i].dis=read();
        sort(L+1,L+1+m);
        int r=0;
        for(int i=1;i<=m;i++){
            int u=L[i].u,v=L[i].v;
            int fa_x=find(u),fa_y=find(v);
            if(fa_x==fa_y) continue;
            ++n;
            fa[n]=fa[fa_x]=fa[fa_y]=n;
            f[n][0]=f[fa_x][0]=f[fa_y][0]=n;
            add(n,fa_x); add(n,fa_y);
            val[n]=L[i].dis;
            if((++r)==n-1) break;
        }
        for(int i=n;i;i--)
            if(!vis[i]) dep[i]=vis[i]=1,dfs(i);
        while(Q--){
            int u=read(),v=read();
            if(find(u)!=find(v)) printf("-1
    ");
            else{
                int lca=Lca(u,v);
                printf("%d
    ",val[lca]);
            }
        }
    }
    
  • 相关阅读:
    树莓派学习记录
    ESP8266
    城轨列控系统
    VMware+CentOS7学习记录
    眼镜
    调试蜂鸣器驱动电路
    假期作业进度6
    假期作业进度5
    假期作业进度4
    假期作业进度3
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/14024331.html
Copyright © 2011-2022 走看看