题目链接: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. Codeforces 568B Symmetric and Transitive

    http://codeforces.com/contest/568/problem/B 题意:题意还挺绕的,其实就是说:要你求出一个图,要求保证其中有至少一个点不连任何边,然后其他连边的点构成的每个联 ...

  2. 关于IoCallDriver

    通常我们所知IoCallDriver是把irp传递给下一层设备,传递到底是什么意思呢?IoCallDriver中实际调用了IopfCallDriver,其代码如下:NTSTATUSFORCEINLIN ...

  3. 流风ASP.NET框架商业版-工作流1.0简介

    流风ASP.NET框架商业版-工作流1.0简介 工作流简介 在流风ASP.NET框架商业版1.0推出后,就有集成工作流的想法,但是由于工作繁忙和其他事情的耽搁,时隔半年之久工作流1.0的版本才姗姗来迟 ...

  4. C#实现目录复制

     摘自:http://www.cnblogs.com/zxjay/archive/2008/10/29/1322517.html FCL提供了文件移动.文件复制.目录移动的方法,但没提供目录复制的 ...

  5. 【POJ2777】Count Color(线段树)

    以下是题目大意: 有水平方向上很多块板子拼成的墙,一开始每一块都被涂成了颜色1,有C和P两个操作,代表的意思是:C X Y Z —— 从X到Y将板子涂成颜色ZP X Y    —— 查询X到Y的板子共 ...

  6. 基于drools创建自己的关系操作符

    我们知道drools提供了12种关系操作符 但是有些时候这12种操作符依然不能满足我们的业务需求,我们可以扩展自己的操作符,下面是为某一航空公司做项目时扩展了操作符,在这分享下 首先,我们要实现的逻辑 ...

  7. std::remove_if

    原型: #include <algorithm>forward_iterator remove_if( forward_iterator start, forward_iterator e ...

  8. Div与table的区别

    1:速度和加载方式方面的区别 div 和 table 的差异不是速度,而是加载方式,速度只能是指网络速度,如果速度足够快,是没有差异的: div 的加载方式是即读即加载,遇到 <div> ...

  9. setTimeout()和setInterval()小结

    写在前面:在写H5游戏时经常需要使用定时刷新页面实现动画效果,比较常用即setTimeout()以及setInterval() setTimeout 描述 setTimeout(code,millis ...

  10. jquery之批量上传图片

    //var btn; /** * * 获取当前时间 */ ==================================js=================================== ...