题目大意:

从一个根节点出发,走最多 x 的长度,问最多能走过多少个节点,图保证是一棵树

dp[0][i][j] , 表示走从i点为根的子树走过了j个点最后回到 i 最少需要多少时间
dp[1][i][j] , 同理,但表示不需要回到 i
那么由儿子不断向父亲更新,有4种情况

1.if(dp[0][u][k+j]<0 || dp[0][u][k+j]>dp[0][v][j]+dp[0][u][k]+2*e[i].d)
                    dp[0][u][k+j]=dp[0][v][j]+dp[0][u][k]+2*e[i].d;

2.if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[0][v][j]+dp[0][u][k]+e[i].d)
                    dp[1][u][k+j]=dp[0][v][j]+dp[0][u][k]+e[i].d;

3.if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[1][v][j]+dp[0][u][k]+e[i].d)
                    dp[1][u][k+j]=dp[1][v][j]+dp[0][u][k]+e[i].d;

4.if(dp[1][u][k+j]<0 || dp[1][u][k+j]>dp[0][v][j]+dp[1][u][k]+2*e[i].d)
                    dp[1][u][k+j]=dp[0][v][j]+dp[1][u][k]+2*e[i].d;

 #include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath> using namespace std;
#define N 505
#define ll long long
ll dp[][N][N];
int fa[N] , n , m;
int first[N],k; struct Edge{
int y , next , d;
Edge(int y= , int next= , int d=):y(y),next(next),d(d){}
}e[N<<]; void add_edge(int x , int y , int d)
{
e[k] = Edge(y , first[x] , d);
first[x] = k++;
} void dfs(int u)
{
dp[][u][] = ;
for(int i=first[u] ; ~i ; i=e[i].next){
int v = e[i].y;
dfs(v);
for(int k=n ; k>= ; k--)
{
if(dp[][u][k]<) continue;
for(int j= ; j<n ; j++){
if(dp[][v][j]<) continue;
if(dp[][u][k+j]< || dp[][u][k+j]>dp[][v][j]+dp[][u][k]+*e[i].d)
dp[][u][k+j]=dp[][v][j]+dp[][u][k]+*e[i].d;
if(dp[][u][k+j]< || dp[][u][k+j]>dp[][v][j]+dp[][u][k]+e[i].d)
dp[][u][k+j]=dp[][v][j]+dp[][u][k]+e[i].d; if(dp[][v][j]<) continue;
if(dp[][u][k+j]< || dp[][u][k+j]>dp[][v][j]+dp[][u][k]+e[i].d)
dp[][u][k+j]=dp[][v][j]+dp[][u][k]+e[i].d;
}
if(dp[][u][k]<) continue;
for(int j= ; j<=n ; j++){
if(dp[][v][j]<) continue;
if(dp[][u][k+j]< || dp[][u][k+j]>dp[][v][j]+dp[][u][k]+*e[i].d)
dp[][u][k+j]=dp[][v][j]+dp[][u][k]+*e[i].d;
}
}
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("a.in" , "r" , stdin);
#endif // ONLINE_JUDGE
int cas = ;
while(scanf("%d" , &n) , n)
{
printf("Case %d:\n" , ++cas);
memset(first , - , sizeof(first));
k = ;
for(int i= ; i<=n ; i++) fa[i]=i;
for(int i= ; i<n ; i++){
int u,v,d;
scanf("%d%d%d" , &u , &v , &d);
u++ , v++;
add_edge(v , u , d);
fa[u] = v;
}
int st;
for(int i= ; i<=n ; i++)
if(fa[i]==i) st = i; memset(dp , - , sizeof(dp));
dfs(st);
/*debug
for(int i=1 ; i<=n ; i++){
for(int j=1 ; j<=n ; j++){
printf("%4I64d" , dp[1][i][j]);
}
cout<<endl;
}*/
scanf("%d" , &m);
for(int i= ; i<m ; i++){
int x;
scanf("%d" , &x);
int ret = ;
for(int t= ; t<=n ; t++){
// cout<<dp[0][1][t]<<" "<<dp[1][1][t]<<endl;
if((dp[][st][t]<=x && dp[][st][t]>=) || (dp[][st][t]<=x && dp[][st][t]>=))
ret = max(ret , t);
}
printf("%d\n" , ret);
}
}
return ;
}

UVALive 4015 树形dp的更多相关文章

  1. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  2. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  3. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  4. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  5. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  6. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  7. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  8. POJ2342 树形dp

    原题:http://poj.org/problem?id=2342 树形dp入门题. 我们让dp[i][0]表示第i个人不去,dp[i][1]表示第i个人去 ,根据题意我们可以很容易的得到如下递推公式 ...

  9. hdu1561 The more, The Better (树形dp+背包)

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1561 思路:树形dp+01背包 //看注释可以懂 用vector建树更简单. 代码: #i ...

随机推荐

  1. laravel 权限管理 常用命令

    use Spatie\Permission\Models\Role;use Spatie\Permission\Models\Permission; $role = Role::create(['na ...

  2. SpringBoot 2.x (5):异常处理与部署WAR项目

    异常处理: SpringBoot的异常处理是不友好的,前端只会显示最基本的错误名称 后端控制台会报出具体的错误,那么我们如何告知前端具体的错误信息呢? 1:对全局异常进行处理 一个测试的Control ...

  3. 浅析Statement和PreparedStatement的区别

    当我们使用java程序来操作sql server时会使用到Statement和PreparedStatement,俩者都可以用于把sql语句从java程序中发送到指定数据库,并执行sql语句.那么如何 ...

  4. [实用技巧] Mac下面如何通过终端快速打开当前文件夹

    Mac mac里面其实很简单,直接输入 open .,注意是open + 英文句点. Windows windows里面是start .,注意是start  + 英文句点.

  5. BST AVL RBT B- B+ 的一些理解

    BST(二叉查找树,排序二叉树),如果数据有序的话,组成的二叉树会形成单列的形式,导致查询效率低AVL(平衡二叉树) 使树的左右高度差的绝对值不超过2,保证了查询效率.但是插入和删除会带来多次旋转,导 ...

  6. JS:输出9*9乘法表

    <html> <head> <title>9*9 multiplication table</title> </head> <body ...

  7. 吸顶条 ---- jQ写法

    <script> $(function () { var barTop = $('#bar').offset().top; //on方法相当于原生的绑定 $(window).on('scr ...

  8. PHP安全之 register_globals

    一.register_globals = Off 和 register_globals = On的区别 register_globals是php.ini里的一个配置,这个配置影响到php如何接收传递过 ...

  9. v8引擎详解

    引用网址: https://blog.csdn.net/swimming_in_it_/article/details/78869549 前言 JavaScript绝对是最火的编程语言之一,一直具有很 ...

  10. 剑指offer8 旋转数组的最小数字

    一种错误写法: class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { int len ...