HDU 3660【树型DP】

题意:

给出一棵树型地图,Alice和Bob从0根结点开始走,轮流选择边,直到到达叶结点,这里的边是单向的。Alice总是选择会使当前达到最小距离的边,Bob相反,求最后的总距离

解题思路:

先求出每个子树的最小值或最大值,然后再更新当前根,如此递归。求最小值还是最大值要根据当前轮到Alice还是Bob选择路径决定。

这题不难,是简单的树型DP,但是这里很可能会卡数据,用vector是过不了的,动态new和free的花销太大。看一下AC的,基本都是1800ms险过的。前面花了几百ms的可能用上了什么奇淫技巧,又或许还有其它更牛b的解法。下面的代码只有用c++提交才能AC,G++会TLE的,为什么呢,不知道,或许是oj上的用G++编译时没有加上o2优化项吧,纯属YY。

View Code
 1 #include <iostream>
2 #include <algorithm>
3
4 using namespace std;
5 const int MAX = 500000 + 1;
6 const int INF = 0x7fffffff;
7
8 struct TNode
9 {
10 int first, next;
11 }Node[MAX];
12 int Dist[MAX], Pos[MAX], DP[MAX], Depth[MAX];
13 int N, R, L;
14 void init()
15 {
16 Depth[0] = 0;
17 memset(Pos, 0, sizeof(Pos));
18 }
19 void addEdge(int f, int t, int v)
20 {
21 Dist[t] = v;
22 if(Pos[f] == 0)
23 Node[f].first = t;
24 else
25 Node[Pos[f]].next = t;
26 Pos[f] = t;
27 Node[t].next = 0;
28 }
29
30 void dfs(int node, int flag)
31 {
32 DP[node] = flag == 0 ? -1 : INF;
33 if(Pos[node] == 0)
34 {
35 DP[node] = 0;
36 return;
37 }
38 for(int ix = Node[node].first; ix != 0; ix = Node[ix].next)
39 {
40 Depth[ix] = Depth[node] + Dist[ix];
41 dfs(ix, !flag);
42 if(DP[ix] == -1 || DP[ix] == INF)
43 continue;
44 int d = Depth[ix] + DP[ix];
45 if(flag == 0)
46 {
47 if(d >= L && d <= R && DP[ix] + Dist[ix] > DP[node])
48 DP[node] = DP[ix] + Dist[ix];
49 }
50 else
51 {
52 if(d >= L && d <= R && DP[ix] + Dist[ix] < DP[node])
53 DP[node] = DP[ix] + Dist[ix];
54 }
55 }
56 }
57
58 int main()
59 {
60 freopen("in.txt", "r", stdin);
61 int f, t, v;
62 while(scanf("%d%d%d", &N, &L, &R) == 3)
63 {
64 init();
65 for(int i = 1; i < N; ++i)
66 {
67 scanf("%d%d%d", &f, &t, &v);
68 addEdge(f, t, v);
69 }
70 dfs(0, 0);
71 if(DP[0] < L || DP[0] > R)
72 printf("Oh, my god!\n");
73 else
74 printf("%d\n", DP[0]);
75 }
76 return 0;
77 }

你可能感兴趣的:(HDU)