hdu4276树形dp
2016-03-12 15:56
218 查看
题目大意:给你一棵树,每个点有个价值,每条边有花费,给你最大的花费t,求从1到n可以得到最大的价值是多少
思路:树形dp。首先从1到n的这条路唯一且每条边走了一次,可以求出这条路的花费(也可以用最短路的spfa去求),如果比给定的花费t大,则不可到达。否则,将这条路上各边的花费置零,t-=sum。然后dp[i][j]表示节点i及其子树花费了j时可获得的最大的价值。每次计算话费是,边的花费需要乘以2.。状态转移方程为:dp[u][j] = max(dp[u][j] , dp[u][up-k]+dp[v][k]);
建图是不能建单向的,必须双向建立!!!因为这个一直wa。还有求最短路径是给出了spfa()但是这个算法置零的时候不方便,可以用judge(),因为路径唯一。。
思路:树形dp。首先从1到n的这条路唯一且每条边走了一次,可以求出这条路的花费(也可以用最短路的spfa去求),如果比给定的花费t大,则不可到达。否则,将这条路上各边的花费置零,t-=sum。然后dp[i][j]表示节点i及其子树花费了j时可获得的最大的价值。每次计算话费是,边的花费需要乘以2.。状态转移方程为:dp[u][j] = max(dp[u][j] , dp[u][up-k]+dp[v][k]);
建图是不能建单向的,必须双向建立!!!因为这个一直wa。还有求最短路径是给出了spfa()但是这个算法置零的时候不方便,可以用judge(),因为路径唯一。。
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <fstream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <iomanip> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define maxn 1000005 #define MOD 1000000007 #define mem(a , b) memset(a , b , sizeof(a)) #define LL long long #define INF 100000000 int n , t; struct edge { int u , v , w; int next; }E[105*2]; int head[105]; int dp[105][505]; int val[105]; int cost[105] , per[105]; int id,sum ,flag ; void add(int u , int v , int w) { E[id].u = u; E[id].v = v; E[id].w = w; E[id].next = head[u]; head[u] = id++; } /* void spfa() { mem(per , -1); for(int i = 2 ; i <= n ; i ++) cost[i] = INF; cost[1] = 0; queue<int>q; q.push(1); while(!q.empty()) { int u = q.front(); q.pop(); for(int i = head[u] ; i >= 0 ; i = E[i].next) { if(cost[E[i].v] > cost[u] + E[i].w) { cost[E[i].v] = cost[u] + E[i].w; per[E[i].v] = i; q.push(E[i].v); } } } for(int i = 1 ; i <= n ; i ++) cout << per[i] << endl; for(int i = per ; i >= 0 ; i = per[i]) { cout << E[i].u << " " << E[i].v << " " << E[i].w << endl; E[i].w = 0; } }*/ /* bool judge(int u,int pre)///找出1~n的路径 { if(u == n)return true; for(int i = head[u]; i != -1 ; i = E[i].next) { int v = E[i].v; if(v == pre)continue; if(judge(v,u)) { sum += E[i].w; E[i].w=0; return true; } } return false;///这句话必须有,因为这一句我没写WA到死..... } */ void judge(int u , int per) { for(int i = head[u] ; i >= 0 ; i = E[i].next ) { if(E[i].v == per) continue; if(E[i].v == n) {sum += E[i].w ; E[i].w = 0 ; flag = 1 ; break;} judge(E[i].v , u); if(flag){sum += E[i].w ;E[i].w = 0; break;} } } void solve(int u , int per) { for(int i = head[u] ; i >= 0 ; i = E[i].next) { if(E[i].v == per) continue; solve(E[i].v , u); for(int j = t ; j >= 2 * E[i].w ; j --) { int up = j - 2 * E[i].w; for(int k = 0 ; k <= up ; k ++) { // if(dp[u][up-k] != -1 && dp[E[i].v][k] != -1) dp[u][j] = max(dp[u][j] , dp[u][up-k] + dp[E[i].v][k]); } } } } int main() { while(scanf("%d %d" , &n , &t) != EOF) { mem(dp , 0);id = 0; mem(head , -1); int u , v , w; for(int i = 1 ; i < n ; i ++) { scanf("%d %d %d" , &u , &v , &w); //if(u > v) swap(u , v); add(u , v , w); add(v , u , w); } for(int i = 1 ; i <= n ; i ++) { scanf("%d" , &val[i]); for(int j = 0 ; j <= t ; j ++) dp[i][j] = val[i]; } flag = sum = 0; judge(1 , -1); //spfa(); if(sum > t) { printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n"); continue; } //cout << sum << endl; t -= sum; solve(1 , -1); printf("%d\n" , dp[1][t]); } }
相关文章推荐
- css技巧篇
- Git与Svn
- 效果惊艳的代码编辑字体推荐
- php-7.0编译模块的出错
- Cocos2dx-- 3.0前后对比
- Java基础知识
- Inna and Choose Options
- 在嵌入式linux下搭建Boa Webserver
- 三. ServerSocket 用法详解(一)
- 改了信仰,”U秒英伟达,卡秒英特尔“
- 从统计看机器学习常见算法
- 【MySQL】MySQL无基础学习和入门之二:MySQL的安装
- react-js-04-组件
- 个人项目四则运算生成程序进展——第三周
- 读《MacTalk·人生元编程》及Mac经常使用软件
- linux sendfile示例
- Linux的文本编辑命令除了vi(vim),还有哪些?
- 【Music】横屏歌词显示效果不好
- 蓝桥杯 地宫寻宝
- MediaRecorder实现微信、QQ、人人、易信等语音录制功能工具:MediaUtilAPI