zoukankan      html  css  js  c++  java
  • ZOJ 3949 Edge to the Root 树形DP

    ZOJ3949

    题意很简单,给定一个树,节点1e+5 问增加一条根节点到任意点的边,使得所有点到根节点的距离和最小,求这个最小距离和。

    当我们连接(1,x)时,距离会减小的点显然是1->x链上在中点之后子树。

    怎样高效计算呢? 其实我们可以在dfs的同时维护根节点到当前节点x这条链的信息, 用当前节点的S减去中点的S 就可以求得使得距离和减小的值,一个dfs后就可以找到最优解。

    代码很简单

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <cstring>
    using namespace std;
    typedef long long LL;
    const int N=200010;
    vector<int> G[N];
    int cnt,st[N],size[N],d[N];
    LL C[N],S[N],ans,all;
    void dfs(int x,int fx){
        d[x]=d[fx]+1;
        all+=d[x];
        size[x]=1;
        for(int i=0;i<G[x].size();i++){
            int v=G[x][i];
            if(v!=fx){
                dfs(v,x);
                size[x]+=size[v];
            }
        }
    }
    void dfs2(int x,int fx){
        if(cnt)S[cnt]-=C[cnt]*size[x];
        st[++cnt]=x;
        C[cnt]=1-2*d[x];
        S[cnt]=S[cnt-1]+C[cnt]*size[x];
        if(fx){
            int mid=(cnt+1)/2;
            ans=min(ans,S[cnt]-S[mid]+1LL*size[st[mid+1]]*d[x]);
        }
        for(int i=0;i<G[x].size();i++){
            int v=G[x][i];
            if(v!=fx)dfs2(v,x);
        }if(--cnt)S[cnt]+=C[cnt]*size[x];
    }
    int T,n;
    int main(){
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            for(int i=1;i<=n;i++)G[i].clear();
            for(int i=1;i<n;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
            }d[all=ans=0]=-1;
            dfs(1,0);
            dfs2(1,0);
            printf("%lld
    ",all+ans);
        }return 0;
    }
    

      

  • 相关阅读:
    js Excel导出
    计算机原理
    Sql Server 连接池
    转/ C# 托管资源和非托管资源
    求两个时间相差多少时间
    计算机基础
    MyEclipse CI 2018.9.0正式发布(附下载)
    DevExpress v18.1新版亮点——ASP.NET Bootstrap篇(二)
    DevExpress v18.1新版亮点——ASP.NET Bootstrap篇(一)
    DevExpress v18.1新版亮点——ASP.NET篇(四)
  • 原文地址:https://www.cnblogs.com/heisenberg-/p/6880171.html
Copyright © 2011-2022 走看看