题目的介绍以及思路完全参考了下面的博客:http://blog.csdn.net/acm_cxlove/article/details/7964739

做这道题主要是为了加强自己对SPFA的代码的训练以及对树dp的一些思路的锻炼。我特地研究了一下树dp的部分

for (int i = t; i >= w; i--){
for (int j = i-w; j >= 0; j--){
dp[u][i] = max(dp[u][i], dp[u][j]+dp[v][i - j - w]);
}
}

循环里面是不能搞错顺序的,外层的i逆序显然,但为什么里层会有问题呢? 因为w是可以=0的,这个时候想像一下,如果j=i-w的话,那么就会有

dp[u][i]=max(dp[u][i],dp[u][i]+dp[v][i-j-w]),但是dp[u][i]是已经更新了的,所以这样会出错,两层循环都必须要逆序。

下面贴一记代码

#pragma warning(disable:4996)
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#define maxn 150
using namespace std; struct Edge
{
int u, v, w;
Edge(){}
Edge(int ui, int vi, int wi) :u(ui), v(vi), w(wi){}
}e[2*maxn]; int n, t;
int val[maxn];
int ecnt; int first[maxn], nxt[2 * maxn]; void add(int u, int v, int w)
{
e[ecnt].u = u; e[ecnt].v = v; e[ecnt].w = w;
nxt[ecnt] = first[u];
first[u] = ecnt++;
} int dis[maxn], vis[maxn];
int p[maxn]; void spfa(int s)
{
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
memset(p, -1, sizeof(p));
queue<int> que;
que.push(s); vis[s] = 1;
dis[s] = 0;
while (!que.empty())
{
int u = que.front(); que.pop();
vis[s] = 0;
for (int i = first[u]; i != -1; i = nxt[i]){
int v = e[i].v;
if (dis[v] > dis[u] + e[i].w){
dis[v] = dis[u] + e[i].w;
p[v] = i;
if (!vis[v]){
que.push(v);
vis[v] = 1;
}
}
}
}
} int dp[maxn][550]; void dfs(int u, int fa)
{
for (int i = first[u]; i != -1; i = nxt[i]){
int v = e[i].v, w = e[i].w * 2;
if (v == fa) continue;
dfs(v, u);
for (int i = t; i >= w; i--){
for (int j = i-w; j >= 0; j--){
dp[u][i] = max(dp[u][i], dp[u][j]+dp[v][i - j - w]);
}
}
}
for (int i = 0; i <= t; i++){
dp[u][i] += val[u];
}
} int main()
{
while (cin >> n >> t)
{
int ui, vi, wi;
memset(first, -1, sizeof(first));
ecnt = 0;
for (int i = 0; i < n - 1; i++){
scanf("%d%d%d", &ui, &vi, &wi);
add(ui, vi, wi);
add(vi, ui, wi);
}
for (int i = 1; i <= n; i++) scanf("%d", val + i);
spfa(1);
if (dis[n]>t) {
puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");
continue;
}
for (int i = n; i != 1; i = e[p[i]].u){
e[p[i]].w = e[p[i] ^ 1].w = 0;
}
t -= dis[n];
memset(dp, 0, sizeof(dp));
dfs(1, -1);
printf("%d\n", dp[1][t]);
}
return 0;
}

HDU4276 The Ghost Blows Light SPFA&&树dp的更多相关文章

  1. HDU4276 The Ghost Blows Light(树形DP+背包)

    题目大概说一棵n个结点树,每个结点都有宝藏,走过每条边要花一定的时间,现在要在t时间内从结点1出发走到结点n,问能获得最多的宝藏是多少. 放了几天的题,今天拿出来集中精力去想,还是想出来了. 首先,树 ...

  2. HDU-4276 The Ghost Blows Light (树形DP+背包)

    题目大意:在一个n个节点的树形迷宫中,1为起点,n为出口.每个节点上有一定价值的珠宝,在节点之间移动的时间已知,问在能走出迷宫的前提下并且不超过m的时间内能收集的最多珠宝是多少? 题目分析:在树上,从 ...

  3. 【HDU 4276】The Ghost Blows Light(树形DP,依赖背包)

    The Ghost Blows Light Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The t ...

  4. HDU4276 - The Ghost Blows Light(树形DP)

    题目大意 给定一棵n个结点的树,每个结点上有一定数量的treasure,经过每条边需要花一定的时间,要求你从结点1出发,在不超过时间T的情况下,最多能够获得的treasure是多少,并且要求结束于结点 ...

  5. HDU 4276-The Ghost Blows Light(树状背包)

    题意: n个房间,每个有一定的钱,一个房间到另一个房间花费一定的时间,给你房间连接树,求在t时间内到达房间m能得到的最大钱数(从房间1(根)出发) 分析: 该题关键是最后要到达m,没有这个条件,就是基 ...

  6. HDU 4276 The Ghost Blows Light (树形DP,变形)

    题意:给定一棵n个节点的树,起点是1,终点是n,每经过一条边需要消耗Ti天,每个点上有一定量的珠宝,要求必须在t天内到达终点才可以将珠宝带出去,问至多能带多少珠宝? 思路: 注意Ti可以为0,而且有可 ...

  7. HDU 4276 The Ghost Blows Light

    K - The Ghost Blows Light Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & ...

  8. BNUOJ 26283 The Ghost Blows Light

    The Ghost Blows Light Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. O ...

  9. 树形DP(01组合背包The Ghost Blows Light HDU4276)

    题意:有n个房间,之间用n-1条道路连接,每个房间都有一个定时炸弹,在T时间后会一起爆炸,第i个房间有pi价值的珠宝,经过每条道路都需要花费一定的时间,一个人从1房间开始 ,从n房间出去,保证再不炸死 ...

随机推荐

  1. const char *p、char const *p、char * const p的区别?

    const char *p和char const *p是一样的,都表示定义一个指向字符常量的指针,指针的内容(字符)不可变.char * const p表示一个指向字符的指针常量,字符可以改变,但是指 ...

  2. lnmp下配置虚拟主机

    一:首先熟悉几个命令 which php      --->  which是通过 PATH环境变量到该路径内查找可执行文件,所以基本的功能是寻找可执行文件 whereis php   ----& ...

  3. Shell脚本升级CentOS php版本v

    #! /bin/sh #1.关闭selinuxcp -rp /etc/selinux/config /etc/selinux/config.baksetenforce 0sed -i '7s/enfo ...

  4. js 函数闭包内部返回函数体调用方法难点解答

    今天在网上,看到一篇关于js函数难点的文章,js函数的一些难点.在那上面提了一下,关于js函数返回另一个函数的问题,并附上了一道面试题: var add = function(x){ var sum ...

  5. PHP 超级全局变量

    超级全局变量在PHP 4.1.0之后被启用, 是PHP系统中自带的变量,在一个脚本的全部作用域中都可用. PHP中预定义了几个超级全局变量(superglobals) ,这意味着它们在一个脚本的全部作 ...

  6. vmware虚拟机上网:NAT搭建局域网

    若是你不知道的情况下,可以编辑虚拟机网络配置,然后恢复默认,vmware会自动给你分配好ip,默认使用的是vmware8,下面的是使用默认的配置 看图 注意:子网的ip一定要在如上图所示的范围 适配器 ...

  7. 加载页面遮挡耗时操作任务页面--第三方开源--AndroidProgressLayout

    在Android的开发中,往往有这种需求,比如一个耗时的操作,联网获取网络图片.内容,数据库耗时读写等等,在此耗时操作过程中,开发者也许不希望用户再进行其他操作(其他操作可能会引起逻辑混乱),而此时需 ...

  8. 选项切换条--第三方开源--SHSegmentControl

    SHSegmentControl在github上的项目主页地址:https://github.com/7heaven/SHSegmentControl SHSegmentControl使用简单,在xm ...

  9. 11g RAC R2 之Linux DNS 配置

    在动手配置前,最好先了解下DNS的理论,以免犯不必要的错误.这都是被坑后的觉悟 -_-!!! Oracle 11g RAC 集群中引入了SCAN(SingleClientAccessName)的概念, ...

  10. WPF 一个弧形手势提示动画

    这是一个操作提示动画,一个小手在屏幕上按照一个弧形来回运动 <Window x:Class="LZRichMediaWall.MainWindow" xmlns=" ...