题目链接: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]的最小值即可。

 #include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
int ans,downcnt[],downsum[];
int upsum[],upcnt[];
int n,m;
int tot,go[],first[],next[];
int dp[][],f[][];
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);insert(y,x);
}
void dfs(int x,int fa){
downcnt[x]=;
downsum[x]=;
upcnt[x]=;
upsum[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
dfs(pur,x);
downcnt[x]+=downcnt[pur];
downsum[x]+=downsum[pur]+downcnt[pur];
}
upcnt[x]=n-downcnt[x];
}
void Dfs(int x,int fa){
if (fa!=){
upcnt[x]=n-downcnt[x];
upsum[x]=upsum[fa]+upcnt[fa]+downsum[fa]-downsum[x]-downcnt[fa]++(downcnt[fa]--downcnt[x])*+;
}else upsum[x]=upcnt[x]=;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
Dfs(pur,x);
}
}
void DP(int x,int fa){
for (int i=;i<=m+;i++)
dp[x][i]=downsum[x],f[x][i]=downsum[x]+upsum[x];
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
DP(pur,x);
for (int j=;j<=m;j++){
dp[x][j]=std::min(dp[x][j],dp[pur][j-]+downsum[x]-downsum[pur]-downcnt[pur]);
if (m-j->=) ans=std::min(ans,f[x][j]+dp[pur][m--j]-downsum[pur]-downcnt[pur]);
}
for (int j=;j<=m;j++){
f[x][j]=std::min(f[x][j],upsum[x]+downsum[x]+dp[pur][j-]-downsum[pur]-downcnt[pur]);
}
}
ans=std::min(ans,dp[x][m]+upsum[x]);
}
int main(){
while (scanf("%d%d",&n,&m)!=EOF){
if (n==&&m==) return ;
tot=;for (int i=;i<=n;i++) first[i]=;
for (int i=;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
x++;y++;
add(x,y);
}
ans=0x7fffffff;
dfs(,);
Dfs(,);
DP(,);
printf("%d\n",ans);
}
}

ZOJ 3188 ZOJ 3188 Treeland Exhibition(树形DP)的更多相关文章

  1. CF 219 D:Choosing Capital for Treeland(树形dp)

    D. Choosing Capital for Treeland 链接:http://codeforces.com/problemset/problem/219/D   The country Tre ...

  2. Codeforces 219D Choosing Capital for Treeland(树形DP)

    题目是给一张边有向的树形图.要选出首都的点,首都要都能走到其他点,因此要反转一些边的方向.问可以选哪几个点作为首都,使它们所需反转边的数量最少. 这题挺好想的,因为做过HDU2196. 首先就不妨设正 ...

  3. ZOJ 3949 Edge to the Root( 树形dp)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3949 题解:树dp真的很直觉,或者说dp真的很直觉.就上周末比赛时其实前一 ...

  4. ZOJ 3626 Treasure Hunt I(树形dp)

    Treasure Hunt I Time Limit: 2 Seconds      Memory Limit: 65536 KB Akiba is a dangerous country since ...

  5. ZOJ 3626 Treasure Hunt I (树形DP,常规)

    题意:给一棵树,一个人站在节点s,他有m天时间去获取各个节点上的权值,并且最后需要回到起点s,经过每条边需要消耗v天,问最少能收获多少权值? 思路: 常规的,注意还得跑回原地s. //#include ...

  6. 【codeforce 219D】 Choosing Capital for Treeland (树形DP)

    Choosing Capital for Treeland Description The country Treeland consists of n cities, some pairs of t ...

  7. Codeforces 490F Treeland Tour 树形dp

    Treeland Tour 离散化之后, 每个节点维护上升链和下降链, 感觉复杂度有点高, 为啥跑这么快.. #include<bits/stdc++.h> #define LL long ...

  8. CodeForces 219D Choosing Capital for Treeland (树形DP)

    题意:给一个树形图,n个节点,n-1条有向边,要求选一个节点作为根,使需要改变方向的边的数目最少.并输出所有可能作为根的点. 思路: 先随便一个点进行DFS,计算将每棵子树的边全部往下时,所需要的费用 ...

  9. Choosing Capital for Treeland CodeForces - 219D (树形DP)

    传送门 The country Treeland consists of n cities, some pairs of them are connected with unidirectional  ...

随机推荐

  1. DPI情况下处理

    1. 字体不要跟着变大小,那就要使用setPixe,不要使用setPointSize 2. 图片可设置QPixmap::setDevicePixelRatio http://doc.qt.io/qt- ...

  2. 如何使用git创建项目,创建分支

    git config -global user.name "Your name" git config -global user.email "you@example.c ...

  3. 关于group by

    <pre name="code" class="sql">关于group by 排序问题 10g 以前sort group by 需要排序 10g ...

  4. How to run Tomcat without root privileges? 常规用户使用tomcat的80端口

    How to run Tomcat without root privileges? 1. The best way is to use jsvc, available as part of the  ...

  5. js深入研究之无法理解的js类代码,extend扩展

    <script type="text/javascript"> function Person(name) { this.name = name; } Person.p ...

  6. cf492B Vanya and Lanterns

    B. Vanya and Lanterns time limit per test 1 second memory limit per test 256 megabytes input standar ...

  7. C++基础回顾2(函数, 指针和引用)

    接着回顾函数.指针和应用. 函数 1.多维数组作为形参时,第一维的大小可以省略(也可以不省略),但是其他维的大小必须指定.比如二维数组形参,int array[3][]不正确,int arry[][1 ...

  8. App架构设计经验谈:接口的设计

    App与服务器的通信接口如何设计得好,需要考虑的地方挺多的,在此根据我的一些经验做一些总结分享,旨在抛砖引玉. 安全机制的设计 现在,大部分App的接口都采用RESTful架构,RESTFul最重要的 ...

  9. java_重写与重载的区别

    重写与重载的区别 重载(Overloading)和重写(Overriding)是Java中两个比较重要的概念.但是对于新手来说也比较容易混淆.本文通过两个简单的例子说明了他们之间的区别. 定义 重载 ...

  10. Map的内容按字母顺序排序

    map有自带的排序功能,但需要重写排序方法,代码如下: package coreJava.com.shindo.corejava.map; import java.util.ArrayList; im ...