zoukankan      html  css  js  c++  java
  • ZOJ 3188 ZOJ 3188 Treeland Exhibition(树形DP)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=3278

    题意:给出一棵树,找出一个不大于长度为m的链,使得其他点到该链的长度之和最小。

    预处理出以下数组:

    (1)downSum[u]:u的所有孩子到达u的距离,downCnt[u]:u子树节点个数;

    (2)upSum[u]:除u子树的节点外其他节点到达u的距离;upCnt[u]:除u子树的节点个数。

    树形DP时,竖线形状的比较简单,我们用dp[u][L]表示以u为子树,向下有一条长度为L的链的最小代价;然后dp[u][m]+upSum[u]就是答案;对于折线形状的,设以u的两个孩子v1、v2组成,则答案为upSum[u]+downSum[u]+dp[v1][j-1]-downSum[v1]-downCnt[v1]+dp[v2][m-1-j]-downSum[v2]-downCnt[v2],因此只要维护upSum[u]+downSum[u]+dp[v1][j-1]-downSum[v1]-downCnt[v1]的最小值即可。

     1 #include<algorithm>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<iostream>
     6 int ans,downcnt[100005],downsum[100005];
     7 int upsum[200005],upcnt[200005];
     8 int n,m;
     9 int tot,go[200005],first[200005],next[200005];
    10 int dp[10005][105],f[10005][105];
    11 void insert(int x,int y){
    12     tot++;
    13     go[tot]=y;
    14     next[tot]=first[x];
    15     first[x]=tot;
    16 }
    17 void add(int x,int y){
    18     insert(x,y);insert(y,x);
    19 }
    20 void dfs(int x,int fa){
    21     downcnt[x]=1;
    22     downsum[x]=0;
    23     upcnt[x]=0;
    24     upsum[x]=0;
    25     for (int i=first[x];i;i=next[i]){
    26         int pur=go[i];
    27         if (pur==fa) continue;
    28         dfs(pur,x);
    29         downcnt[x]+=downcnt[pur];
    30         downsum[x]+=downsum[pur]+downcnt[pur];
    31     }
    32     upcnt[x]=n-downcnt[x];
    33 }
    34 void Dfs(int x,int fa){
    35     if (fa!=0){
    36         upcnt[x]=n-downcnt[x];
    37         upsum[x]=upsum[fa]+upcnt[fa]+downsum[fa]-downsum[x]-downcnt[fa]+1+(downcnt[fa]-1-downcnt[x])*2+1;
    38     }else upsum[x]=upcnt[x]=0;
    39     for (int i=first[x];i;i=next[i]){
    40         int pur=go[i];
    41         if (pur==fa) continue;
    42         Dfs(pur,x);
    43     }
    44 }
    45 void DP(int x,int fa){
    46     for (int i=0;i<=m+1;i++)
    47      dp[x][i]=downsum[x],f[x][i]=downsum[x]+upsum[x];
    48     for (int i=first[x];i;i=next[i]){
    49         int pur=go[i];
    50         if (pur==fa) continue;
    51         DP(pur,x);
    52         for (int j=1;j<=m;j++){
    53             dp[x][j]=std::min(dp[x][j],dp[pur][j-1]+downsum[x]-downsum[pur]-downcnt[pur]);
    54             if (m-j-1>=0) ans=std::min(ans,f[x][j]+dp[pur][m-1-j]-downsum[pur]-downcnt[pur]);
    55         }
    56         for (int j=1;j<=m;j++){
    57             f[x][j]=std::min(f[x][j],upsum[x]+downsum[x]+dp[pur][j-1]-downsum[pur]-downcnt[pur]);
    58         }
    59     }
    60     ans=std::min(ans,dp[x][m]+upsum[x]);
    61 }
    62 int main(){
    63     while (scanf("%d%d",&n,&m)!=EOF){
    64         if (n==0&&m==0) return 0;
    65         tot=0;for (int i=1;i<=n;i++) first[i]=0;
    66         for (int i=1;i<n;i++){
    67             int x,y;
    68             scanf("%d%d",&x,&y);
    69             x++;y++;
    70             add(x,y);
    71         }
    72         ans=0x7fffffff;
    73         dfs(1,0);
    74         Dfs(1,0);
    75         DP(1,0);
    76         printf("%d
    ",ans);
    77     }
    78 }
  • 相关阅读:
    下载vue-devtools插件的步骤
    弄清 CSS3 的 transition 和 animation
    js与多行字符串
    swift 上手
    liunux 修改hostname
    linux 下使用配置文件
    linux安装oracle11g
    jQueryt过滤选择器
    Javascript并发模型和事件循环
    CSS生僻问题一网打尽
  • 原文地址:https://www.cnblogs.com/qzqzgfy/p/5553917.html
Copyright © 2011-2022 走看看