题目链接: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 526E Transmitting Levels

    http://codeforces.com/contest/526/problem/E 题意:给一个环,每个点有权值,每次给一个数B,求把这个环切割成若干部分,每个部分不超过B,至少要切成几块? #i ...

  2. POJ 2540 Hotter Colder

    http://poj.org/problem?id=2540 题意:给你每次行走的路径,而且告诉你每次离一个点光源是远了还是近了,要求每次光源可能存在的位置的面积. 思路:如果出现"same ...

  3. 在Fragment中实现百度地图,定位到当前位置(基于SDKv2.1.0)

    使用最新版本的百度地图需要注意的几个地方: 1.libs文件夹下要有android-support-v4.jar.baidumapapi_v2_1_0.jar.locSDK_3.1.jar三个jar包 ...

  4. 面试题32.从1到n整数中1出现的次数

    题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数.例如输入12,从 1到12这些整数中包含1的数字中1,10,11和12,1一共出现了5次 本题可以直接变量1到n的n个数然后分别计 ...

  5. POJ 3378

    题目链接 查找长度为5的上升序列总数 用的树状数组+高精度 用树状数组求在i前面比i小的数有几个 用的4个树状数组,A[i][j]表示长度为i的以j为结尾的个数,A[i][j]=A[i-1][1... ...

  6. Bubble Sort 冒泡排序

    //Bubble Sort ( O(n²)) public class TestBubbleSort { public int[] bubbleSortArray(int[] arr){ ; i &l ...

  7. hibernate分页查询的各种方法

    统计总数: public Integer countAll1() { String hql = "select count(*) from News as news"; List ...

  8. Javascript:一个优雅的时钟

    实现效果: 准备工作: 1# 定时器 相关知识了解 2#javascript Date(日期)对象 3# 准备效果所用图片 实现原理: 1# 获取当前时间: var time=new Date(); ...

  9. HDU 2689 sort it - from lanshui_Yang

    Problem Description You want to processe a sequence of n distinct integers by swapping two adjacent ...

  10. NOTIFYICONDATA结构

    //农机调度项目代码 NOTIFYICONDATA m_notifyData; m_notifyIcon.ChangeIcon(IDI_PAUSE, _T("监控终端server已暂停&qu ...