HDU 4276 树形DP
2013-07-04 20:42
288 查看
题意:给你n个点,n-1条边构成树,每条边有边树,每个点有点权(表示走每条边的时间),问在时间T从点1走到点n,能够得到最多的点权有多少。
我的思路:3个Dfs,第一个用来标记从1到n的路径,第二个用来求每个点除必走关键路径外所能得到的最大点权,第三次则是用父亲节点更新儿子节点能获得的最大值。
网上的思路:首先spfa求一次最短路,如果从1到n的最短花费都小于总时间,则是不可能。而且在最短路的时候记录每个节点的父节点,以及边的编号然后将最短路径上的所有边权置为0.将总时间减去最短路径。这样处理的目的是,显然最短路上的边只会走一遍才是最优的,而且剩下的边要么不走,要么走两次,而且DFS求一次树形DP之后,不需要考虑回到n的情况,因为1-n的最短路径走了一遍,其它边走0次或两次,肯定是回到n的。
这样就成了树上的分组背包了。
网上的思路大概懂了,懒得敲了,这里就附上我自己拙计的思路的代码吧。
我的思路:3个Dfs,第一个用来标记从1到n的路径,第二个用来求每个点除必走关键路径外所能得到的最大点权,第三次则是用父亲节点更新儿子节点能获得的最大值。
网上的思路:首先spfa求一次最短路,如果从1到n的最短花费都小于总时间,则是不可能。而且在最短路的时候记录每个节点的父节点,以及边的编号然后将最短路径上的所有边权置为0.将总时间减去最短路径。这样处理的目的是,显然最短路上的边只会走一遍才是最优的,而且剩下的边要么不走,要么走两次,而且DFS求一次树形DP之后,不需要考虑回到n的情况,因为1-n的最短路径走了一遍,其它边走0次或两次,肯定是回到n的。
这样就成了树上的分组背包了。
网上的思路大概懂了,懒得敲了,这里就附上我自己拙计的思路的代码吧。
#include <cstdio> #include <cstring> #include <string> #include <iostream> #include <queue> #include <algorithm> #include <map> #include <vector> #include <stack> using namespace std; #define ll long long #define int64 __int64 #define M 100005 #define N 10005 #define inf 1<<30 #define mod 1000000007 struct node { int ev , cost; }; int n , t , dp[105][505] , val[105]; int mintime , minval; bool path[105]; vector<node> son[105]; bool Dfs(int s , int fa) { if (s == n) { minval += val[s]; path[s] = 1; return true; } int i , up = son[s].size(); for (i = 0 ; i < up ; i++) { int v = son[s][i].ev; int cost = son[s][i].cost; if (v == fa)continue; if (Dfs(v,s)) { mintime += cost; minval += val[s]; path[s] = 1; return true; } } return false; } void Dfs1(int s , int fa) { int i , j , k , up = son[s].size() , mainpath = -1; for (i = 0 ; i < up ; i++) { int v = son[s][i].ev; int cost = son[s][i].cost; if (v == fa)continue; if (path[v]) { mainpath = v; continue; } Dfs1(v,s); for (j = mintime ; j >= 2*cost ; j--) { for (k = 0 ; k+2*cost <= j ; k++) { dp[s][j] = max(dp[s][j],dp[s][j-k-2*cost]+dp[v][k]+val[v]); } } } if (mainpath != -1) Dfs1(mainpath,s); } void Dfs2(int s , int fa) { int i , j , k , v , cost , up = son[s].size() , mainpath = -1; for (i = 0 ; i < up ; i++) { v = son[s][i].ev; if (v == fa)continue; if (path[v]) { mainpath = v; break; } } if (mainpath == -1)return; v = mainpath; cost = son[s][i].cost; for (j = mintime ; j > 0 ; j--) { for (k = 0 ; k <=j ; k++) { dp[v][j] = max(dp[v][j],dp[v][j-k]+dp[s][k]); } } Dfs2(mainpath,s); } int main() { int i; while (~scanf("%d%d",&n,&t)) { for (i = 1 ; i < n ; i++) { int s , e , w; scanf("%d%d%d",&s,&e,&w); node temp; temp.cost = w; temp.ev = e; son[s].push_back(temp); temp.ev = s; son[e].push_back(temp); } for (i = 1 ; i <= n ; i++)scanf("%d",val+i); mintime = minval = 0; memset(path , 0 , sizeof path); Dfs(1,0); if (mintime > t) printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n"); else { mintime = t-mintime; memset(dp , 0 , sizeof dp); Dfs1(1,0); Dfs2(1,0); printf("%d\n",dp [mintime]+minval); } for (i = 1 ; i <= n ; i++)son[i].clear(); } return 0; }
相关文章推荐
- HDU 4276 The Ghost Blows Light(树形DP)
- HDU 4276 树形DP The Ghost Blows Light
- HDU 4276 The Ghost Blows Light 树形dp
- 【树形DP】【HDU 4276】The Ghost Blows Light
- HDU 4276 The Ghost Blows Light(12年长春 树形DP+spfa)
- HDU 4276 树形dp+spfa+分组背包
- hdu 4276 The Ghost Blows Light - 树形dp
- hdu 4276 树形dp
- hdu 4276 The Ghost Blows Light(树形DP+最短路+分组背包)好题。。。
- HDU 4276 The Ghost Blows Light [树形背包DP]
- HDU 4276 The Ghost Blows Light (树形DP,变形)
- hdu 4276 树形dp + 最短路
- hdu 4276 The Ghost Blows Light (树形dp)
- 【HDU 4276】The Ghost Blows Light(树形DP,依赖背包)
- HDU 4276 The Ghost Blows Light【树形DP】
- HDU - 4276(转树形dp)
- hdu 4276 The Ghost Blows Light(DP-树形DP)
- hdu 4276 树形DP + 分组背包
- HDU 4276 The Ghost Blows Light (树形DP)
- hdu 4276 树形DP