zoukankan      html  css  js  c++  java
  • EZOJ #386 最小生成树

    分析

    先建出最小生成树

    之后每次倍增找环即可

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    struct node {
        int x,y,z,is,id;
    };
    node d[400100];
    int head[800100],nxt[800100],to[800100],w[800100],cnt,res,dep[400100];
    int pr[400100][23],sum[400100][23],n,m,ans[400100],fa[400100],tot;
    inline void add(int x,int y,int z){
        nxt[++cnt]=head[x];
        head[x]=cnt;
        to[cnt]=y;
        w[cnt]=z;
        nxt[++cnt]=head[y];
        head[y]=cnt;
        to[cnt]=x;
        w[cnt]=z;
    }
    inline void dfs(int x,int fa){
        dep[x]=dep[fa]+1;
        pr[x][0]=fa;
        for(int i=head[x];i;i=nxt[i])
          if(to[i]!=fa)sum[to[i]][0]=w[i],dfs(to[i],x);
    }
    inline int lca(int x,int y){
        if(dep[x]<dep[y])swap(x,y);
        int len=dep[x]-dep[y],wh=0;
        for(int i=0;i<=20;i++)
          if((1<<i)&len)wh=max(wh,sum[x][i]),x=pr[x][i];
        if(x==y)return wh;
        for(int i=20;i>=0;i--)
          if(pr[x][i]!=pr[y][i]){
              wh=max(wh,max(sum[x][i],sum[y][i]));
              x=pr[x][i];
              y=pr[y][i];
          }
        wh=max(wh,max(sum[x][0],sum[y][0]));
        return wh;
    }
    inline bool cmp(const node a,const node b){return a.z<b.z;}
    inline int sf(int x){return fa[x]==x?x:fa[x]=sf(fa[x]);}
    signed main(){
        int i,j,k;
        scanf("%lld%lld",&n,&m);
        for(i=1;i<=m;i++){
          scanf("%lld%lld%lld",&d[i].x,&d[i].y,&d[i].z);
          d[i].id=i;
        }
        for(i=1;i<=n;i++)fa[i]=i;
        sort(d+1,d+m+1,cmp);
        for(i=1;i<=m;i++){
          int x=d[i].x,y=d[i].y;
          if(sf(x)==sf(y))continue;
          fa[sf(y)]=sf(x);
          add(x,y,d[i].z);
          res+=d[i].z;
          tot++;
          d[i].is=1;
          if(tot==n-1)break;
        }
        dfs(1,0);
        for(i=1;i<=20;i++)
          for(j=1;j<=n;j++)
            pr[j][i]=pr[pr[j][i-1]][i-1],
            sum[j][i]=max(sum[j][i-1],sum[pr[j][i-1]][i-1]);
        for(i=1;i<=m;i++){
          if(d[i].is)ans[d[i].id]=res;
            else ans[d[i].id]=res+d[i].z-lca(d[i].x,d[i].y);
        }
        for(i=1;i<=m;i++)printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    mongodb的账户管理
    mongo备份与恢复
    mongo索引
    聚合aggregate
    07-【jsp基本了解】
    Servlet登录小案例
    06-【servletconfig、servletContext 】
    05-【session、cookie】
    jQuery
    04-【servlet转发和重定向】
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/11520492.html
Copyright © 2011-2022 走看看