1 条题解

  • 0
    @ 2026-6-14 14:42:46

    // Kruskal 重构树 O(MlogM+NlogN)
    #include<bits/stdc++.h>
    using namespace std;
    
    const int N=30005,M=60005; //重构树 点数=2N,边数=4N
    int idx,h[N],to[M],ne[M];
    void add(int u,int v){
      to[++idx]=v;ne[idx]=h[u];h[u]=idx;
      to[++idx]=u;ne[idx]=h[v];h[v]=idx;
    }
    int n,m,q,p,val[N]; //val新建点点权
    struct E{int x,y,w;}e[M]; //原图边
    int pa[N]; //并查集数组
    int dep[N],fa[N][21]; //树上倍增数组
    
    int find(int x){ //并查集查找
      return pa[x]==x?x:pa[x]=find(pa[x]);
    }
    void kruskal(){
      for(int i=1;i<=n;++i) pa[i]=i;
      sort(e+1,e+1+m,[&](E a,E b){return a.w<b.w;});
      
      for(int i=1;i<=m;++i){
        int x=find(e[i].x),y=find(e[i].y);
        if(x!=y){
          val[++p]=e[i].w; //新建点点权=边权
          pa[p]=pa[x]=pa[y]=p; //点x,y均指向点p
          add(p,x); add(p,y);  //x,y均与p连无向边
        }
      }
    }
    void dfs(int x,int f){ //预处理dep,fa数组
      dep[x]=dep[f]+1; fa[x][0]=f;
      for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1];
      for(int i=h[x];i;i=ne[i]){
        int y=to[i];
        if(y!=f) dfs(y,x);
      }
    }
    int lca(int x,int y){ //倍增求lca
      if(dep[x]<dep[y]) swap(x,y); //让x更深
      for(int i=20;i>=0;i--)if(dep[fa[x][i]]>=dep[y]) x=fa[x][i]; //x向上跳到y的同一层
      if(x==y) return x;
      for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; //x,y一起向上跳
      return fa[x][0];
    }
    int main(){
      ios::sync_with_stdio(0);cin.tie(0);
      cin>>n>>m>>q;
      for(int i=1,u,v,w;i<=m;++i){
        cin>>u>>v>>w;
        e[i]={u,v,w};
      }
      
      p=n;      //新建点编号初值
      kruskal();//重构树
      dfs(p,0); //倍增预处理dep,fa数组
      for(int u,v;q--;){
        cin>>u>>v;
        printf("%d\n",val[lca(u,v)]);
      }
    }
    
    • 1

    D146【模板】Kruskal 重构树 [Bzoj3732] Network

    信息

    ID
    12488
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    4
    已通过
    3
    上传者