zoukankan      html  css  js  c++  java
  • bzoj3611: [Heoi2014]大工程

    Description

    国家有一个大工程,要给一个非常大的交通网络里建一些新的通道。 
    我们这个国家位置非常特殊,可以看成是一个单位边权的树,城市位于顶点上。 
    在 2 个国家 a,b 之间建一条新通道需要的代价为树上 a,b 的最短路径。
     现在国家有很多个计划,每个计划都是这样,我们选中了 k 个点,然后在它们两两之间 新建 C(k,2)条 新通道。
    现在对于每个计划,我们想知道:
     1.这些新通道的代价和
     2.这些新通道中代价最小的是多少 
    3.这些新通道中代价最大的是多少

    Input

    第一行 n 表示点数。

     接下来 n-1 行,每行两个数 a,b 表示 a 和 b 之间有一条边。
    点从 1 开始标号。 接下来一行 q 表示计划数。
    对每个计划有 2 行,第一行 k 表示这个计划选中了几个点。
     第二行用空格隔开的 k 个互不相同的数表示选了哪 k 个点。

    Output

    输出 q 行,每行三个数分别表示代价和,最小代价,最大代价。 

    建出虚树,在上面树形dp求一下关键点之间的最近、最远距离,距离和。

    虚树不需要真正建出来并连边,只要保留虚树中点按dfs序排序后的数组即可在上面dfs

    #include<cstdio>
    #include<algorithm>
    const int N=1.01e6+7,inf=0x3f3f3f3f;
    int n,m;
    int es[N*2],enx[N*2],e0[N],ep=2,stk[N],stp=0;
    int fa[N],sz[N],son[N],top[N],dep[N],id[N],id2[N],idr[N],idp=0,ps[N];
    int ed[N],tk=0;
    void hld_pre(){
        idr[id[1]=++idp]=stk[++stp]=1;
        for(int i=1;i<=n;++i)sz[i]=1;
        while(stp){
            int w=stk[stp],&e=e0[w];
            if(!e){
                --stp;
                id2[w]=idp;
                int f=fa[w];
                sz[f]+=sz[w];
                if(sz[w]>sz[son[f]])son[f]=w;
                continue;
            }
            int u=es[e];e=enx[e];
            if(u==fa[w])continue;
            fa[idr[id[u]=++idp]=stk[++stp]=u]=w;
            dep[u]=dep[w]+1;
        }
        for(int t=1;t<=idp;++t){
            int w=idr[t],f=fa[w];
            top[w]=(son[f]==w?top[f]:w);
        }
    }
    int lca(int x,int y){
        int a=top[x],b=top[y];
        while(a!=b){
            if(dep[a]>dep[b])x=fa[a],a=top[x];
            else y=fa[b],b=top[y];
        }
        return dep[x]<dep[y]?x:y;
    }
    inline int cmp(int a,int b){return id[a]<id[b];}
    int mx[N][2],mn[N][2],FA[N],pp,SZ[N];
    long long sum[N];
    void push(){
        int w=stk[++stp]=pp++;
        sum[w]=0;
        mx[w][1]=-inf;
        mn[w][1]=inf;
        if(ed[ps[w]]==tk){
            SZ[w]=1;
            mx[w][0]=0;
            mn[w][0]=0;
        }else{
            SZ[w]=0;
            mx[w][0]=-inf;
            mn[w][0]=inf;
        }
    }
    void mxs(int*a,int b){
        if(b>=a[0])a[1]=a[0],a[0]=b;
        else if(b>a[1])a[1]=b;
    }
    void mns(int*a,int b){
        if(b<=a[0])a[1]=a[0],a[0]=b;
        else if(b<a[1])a[1]=b;
    }
    void mxs(int&a,int b){if(a<b)a=b;}
    void mns(int&a,int b){if(a>b)a=b;}
    void dfs(){
        long long ans=0;
        pp=0;
        int mxv=-inf,mnv=inf;
        push();
        while(stp){
            int x=stk[stp];
            if(pp<m&&id[ps[pp]]<=id2[ps[x]]){
                FA[pp]=x;
                push();
            }else{
                --stp;
                if(x){
                    int f=FA[x],e=dep[ps[x]]-dep[ps[f]];
                    mxs(mx[f],mx[x][0]+e);
                    mns(mn[f],mn[x][0]+e);
                    long long s1=sum[x]+e*(long long)SZ[x];
                    ans+=sum[f]*SZ[x]+s1*SZ[f];
                    SZ[f]+=SZ[x];
                    sum[f]+=s1;
                }
                mxs(mxv,mx[x][0]+mx[x][1]);
                mns(mnv,mn[x][0]+mn[x][1]);
            }
        }
        printf("%lld %d %d
    ",ans,mnv,mxv);
    }
    int main(){
        scanf("%d",&n);
        for(int i=1,a,b;i<n;++i){
            scanf("%d%d",&a,&b);
            es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
            es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
        }
        hld_pre();
        int T;
        for(scanf("%d",&T);T;--T){
            scanf("%d",&m);
            ++tk;
            for(int i=0;i<m;++i)scanf("%d",ps+i),ed[ps[i]]=tk;
            std::sort(ps,ps+m,cmp);
            for(int i=m-1;i;--i){
                int x=lca(ps[i-1],ps[i]);
                if(ed[x]!=tk)ps[m++]=x;
            }
            std::sort(ps,ps+m,cmp);
            ps[m]=0;
            dfs();
        }
        return 0;
    }
  • 相关阅读:
    STL 里出现 warning C4018: “<”: 有符号/无符号不匹配
    (程序员面试题精选(02))-设计包含min函数的栈
    C++的内存分配问题
    C++ const解析(转)
    关于QQ一些功能的实现(转)
    C++中堆和栈的完全解析(转)
    关于Windows的TortoiseSVN 不能Check out google 代码的问题
    WPF笔记(2.6 ViewBox)——Layout
    我也设计模式——0.前言
    WPF笔记(2.8 常用的布局属性)——Layout
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6874523.html
Copyright © 2011-2022 走看看