zoukankan      html  css  js  c++  java
  • BZOJ 1977: [BeiJing2010组队]次小生成树 Tree 倍增 最小生成树

    好吧我太菜了又调了一晚上。。。QAQ


    先跑出最小生成树,标记树边,再用树上倍增的思路,预处理出:

      f[u][i] :距离u为2^i的祖先

      h[u][i][0/1] :距u点在2^i范围内的最长边和次长边

    然后枚举每一条非树边(u,v),会与原先的最小生成树构成一个环,而之前预处理出的数据可以快速找到(u,v)在最小生成树上的最大和次大边,来更新答案

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #define int long long
    #define R register int
    using namespace std;
    inline int g() {
        R ret=0,fix=1;register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-1:fix;
        do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret*fix;
    }
    struct node{int u,v,w;bool operator <(const node & y) const { return w<y.w;}}a[600010];
    struct edge{int v,w,nxt;}e[200010];
    int n,m,cnt,mx,mmx,mn=0x3f3f3f3f,ans,tot; 
    int fir[100010],f[100010][20],h[100010][20][2],fa[100010],d[100010];
    bool tr[600010];
    inline void add(int u,int v,int w) {e[++cnt].v=v,e[cnt].nxt=fir[u],e[cnt].w=w,fir[u]=cnt;}
    inline void ins(int u,int v,int w) {add(u,v,w),add(v,u,w);}
    inline int getf(int x) {return x==fa[x]?x:fa[x]=getf(fa[x]);}
    inline void dfs(int u,int fa) {
        for(R i=fir[u];i;i=e[i].nxt) {
            R v=e[i].v; if(v==fa) continue;
            f[v][0]=u,h[v][0][0]=e[i].w,d[v]=d[u]+1;
            for(R i=1;d[v]>=(1<<i);++i) {
                f[v][i]=f[f[v][i-1]][i-1]; 
                h[v][i][0]=max(h[v][i-1][0],h[f[v][i-1]][i-1][0]);
                if(h[v][i-1][0]==h[f[v][i-1]][i-1][0]) 
                    h[v][i][1]=max(h[v][i-1][1],h[f[v][i-1]][i-1][1]);
                else {
                    h[v][i][1]=min(h[v][i-1][0],h[f[v][i-1]][i-1][0]);
                    h[v][i][1]=max(h[v][i-1][1],h[v][i][1]);
                    h[v][i][1]=max(h[v][i][1],h[f[v][i-1]][i-1][1]);
                }
            } dfs(v,u);
        }
    }
    inline int lca(int u,int v) {
        if(d[u]<d[v]) swap(u,v); R lim=log2(d[u])+1; 
        for(R j=lim;j>=0;--j) if(d[f[u][j]]>=d[v]) u=f[u][j];
        if(u==v) return u; 
        for(R j=lim;j>=0;--j) if(f[u][j]!=f[v][j]) u=f[u][j],v=f[v][j];
        return f[u][0];
    }
    inline void calc(int u,int fa,int w) {
        mx=0,mmx=0; R lim=log2(d[u]-d[fa])+1;
        for(R i=lim;i>=0;--i) if(d[u]-d[fa]>=(1<<i)){
            if(h[u][i][1]>mx) mmx=mx,mx=h[u][i][0];
            mx=max(h[u][i][0],mx); mmx=max(mmx,h[u][i][1]),u=f[u][i];
        }
        if(mx!=w) mn=min(mn,w-mx); else mn=min(mn,w-mmx);
    }
    signed main() {
        n=g(),m=g();
        for(R i=1;i<=n;++i) fa[i]=i;
        for(R i=1;i<=m;++i) a[i].u=g(),a[i].v=g(),a[i].w=g();
        sort(a+1,a+m+1);
        for(R i=1;i<=m&&tot<n;++i) {
            R uf=getf(a[i].u),vf=getf(a[i].v);
            if(uf==vf) continue;
            fa[uf]=vf; ans+=a[i].w; tr[i]=true;
            ins(a[i].u,a[i].v,a[i].w); ++tot;
        } dfs(1,0);
        for(R i=1;i<=m;++i) if(!tr[i]) {
            R L=lca(a[i].u,a[i].v);
            calc(a[i].u,L,a[i].w); calc(a[i].v,L,a[i].w);
        } printf("%lld
    ",ans+mn);
    }

    2019.04.09

  • 相关阅读:
    《DSP using MATLAB》 示例 Example 9.12
    《DSP using MATLAB》示例 Example 9.11
    《DSP using MATLAB》示例 Example 9.10
    《DSP using MATLAB》示例Example 9.9
    《DSP using MATLAB》示例 Example 9.8
    《DSP using MATLAB》示例Example 9.7
    《DSP using MATLAB》示例 Example 9.6
    《DSP using MATLAB》示例Example 9.5
    《DSP using MATLAB》示例 Example 9.4
    (转载)【C++11新特性】 nullptr关键字
  • 原文地址:https://www.cnblogs.com/Jackpei/p/10674469.html
Copyright © 2011-2022 走看看