类型:树形DP
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3660
思路:令状态dp[i]表示以i为根时到叶子节点的最优值,当i为bob时,取最大值,当i为alice时,取最小值。用dist[i]记录从0节点到当前节点的路径的长度。
当搜索到某条边(u, v)时,根据题意知始终有:dist[u] + dp[v] + p[i].w >= l && dist[u] + dp[v] + p[i].w <= r成立。根据该条件判断是否选择当前边。
// hdoj 3660 Alice and Bob's Trip
// tle ac 796MS 10012K
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
using namespace std;
#define FOR(i,a,b) for(i = (a); i < (b); ++i)
#define FORE(i,a,b) for(i = (a); i <= (b); ++i)
#define CLR(a,b) memset(a,b,sizeof(a))
const int MAXN = 500010;
const int INF = 0x7f7f7f7f;
int dp[MAXN], head[MAXN], dist[MAXN];
int cnt, n, r, l, minsum;
struct node {
int v, nxt, w;
}p[MAXN];
void dfs(int u, int sign) {
for(int i = head[u]; i != -1; i = p[i].nxt) {
int v = p[i].v;
dist[v] = dist[u] + p[i].w;
dfs(p[i].v, !sign);
//!!!
if(dist[u] + dp[v] + p[i].w >= l && dist[u] + dp[v] + p[i].w <= r) {
if(dp[u] == 0) {
dp[u] = dp[v] + p[i].w;
continue;
}
if(sign == 1) {
if(dp[u] < dp[v] + p[i].w)
dp[u] = dp[v] + p[i].w;
}
else if(dp[u] > dp[v] + p[i].w)
dp[u] = dp[v] + p[i].w;
}
}
}
int getint() {
char c=getchar();
int t=0;
while (c<'0' || c>'9') {
c=getchar();
}
while (c>='0' && c<='9') {
t=t*10+c-'0';
c=getchar();
}
return t;
}
int main() {
int i;
int u, v, w;
while(scanf("%d %d %d", &n, &l, &r) != EOF) {
CLR(head, -1);
cnt = 0;
CLR(dp, 0);
CLR(dist, 0);
FOR(i, 0, n - 1) {
u = getint(), v = getint(), w = getint();
p[cnt].v = v;
p[cnt].w = w;
p[cnt].nxt = head[u];
head[u] = cnt++;
}
dfs(0, 1);
if(dp[0] == 0)
printf("Oh, my god!\n");
else
printf("%d\n", dp[0]);
}
return 0;
}