【题意】:给出一棵n个结点的有向树,两个人一起走,轮流决策,Alice的目的是使最后的距离最小,Bob的目的是使最后的距离最大。问最后的距离能否满足在区间[L,R]。需要走到不能走的地方才能停。
【题解】:这题要注意的是,可能还没有走到叶子结点就停止了。
然后就是一个树形dp。
对于一棵给定的树,每个结点轮到谁决策是确定的。
根据当前不同的人,选择满足当前区间[L',R']最大值或者最小值。
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "algorithm"
5 #include "vector"
6 #include "queue"
7 #include "cmath"
8 #include "string"
9 #include "cctype"
10 #include "map"
11 #include "iomanip"
12 using namespace std;
13 #define pb push_back
14 #define mp make_pair
15 #define fi first
16 #define se second
17 #define lc(x) (x << 1)
18 #define rc(x) (x << 1 | 1)
19 #define lowbit(x) (x & (-x))
20 #define ll long long
21 #define maxm 600000
22 #define maxn 505000
23
24 int n, L, R;
25 int tot, eh[maxn];
26 int dp[maxn];
27
28 struct Edge {
29 int v, w, next;
30 }et[maxm];
31
32 void init() {
33 tot = 0;
34 memset(eh, -1, sizeof(eh));
35 }
36
37 void addedge(int u, int v, int w) {
38 Edge e = {v, w, eh[u]};
39 et[tot] = e;
40 eh[u] = tot++;
41 }
42
43 void dfs(int u, int L, int R, int flag) {
44 dp[u] = 0;
45 for(int i = eh[u]; i != -1; i = et[i].next) {
46 int v = et[i].v, w = et[i].w;
47 dfs(v, L - w, R - w, !flag);
48 if(dp[v] + w >= L && dp[v] + w <= R) {
49 if(dp[u] == 0) dp[u] = dp[v] + w;
50 else {
51 if(flag) dp[u] = max(dp[u], dp[v] + w);
52 else dp[u] = min(dp[u], dp[v] + w);
53 }
54 }
55 }
56 }
57
58 int main() {
59 int u, v, w;
60 while(~scanf("%d%d%d", &n, &L, &R)) {
61 init();
62 for(int i = 1; i < n; i++) {
63 scanf("%d%d%d", &u, &v, &w);
64 addedge(u, v, w);
65 }
66 dfs(0, L, R, 1);
67 if(R < L || dp[0] < L || dp[0] > R) printf("Oh, my god!\n");
68 else printf("%d\n", dp[0]);
69 }
70 return 0;
71 }
72