A. The Fair Nut and the Best Path
https://codeforces.com/contest/1083/problem/A
题意:
在一棵树内找一条路径,使得从起点到终点的最后剩下的油最多。(中途没油了不能再走了,可以在每个点加wi升油,减少的油量为路径长度)。
分析:
dfs一遍可以求出子树内所有点到子树根节点的最大的路径和次大的路径,然后可以直接合并取max,并且和从根节点出发的路径取max。
两条最大的和次大的合并可能不合法的。从最大的走上来后,不一定可以从根节点在走回去。但是即使不合法的取max是没有影响的,这样的路径一定不是更优的。
代码:
1 #include<cstdio>
2 #include<algorithm>
3 #include<cstring>
4 #include<iostream>
5 #include<cmath>
6 #include<cctype>
7 #include<set>
8 #include<queue>
9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13
14 inline int read() {
15 int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16 for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18
19 const int N = 300005;
20
21 struct Edge{
22 int to, nxt, w;
23 Edge() {}
24 Edge(int a,int b,int c) { to = a, nxt = b, w = c; }
25 }e[N << 1];
26 int head[N], w[N], En;
27
28 inline void add_edge(int u,int v,int w) {
29 ++En; e[En] = Edge(v, head[u], w); head[u] = En;
30 ++En; e[En] = Edge(u, head[v], w); head[v] = En;
31 }
32
33 LL f[N], Ans;
34 void dfs(int u,int fa) {
35 f[u] = w[u];
36 LL mx1 = -1e18, mx2 = -1e18;
37 for (int i = head[u]; i; i = e[i].nxt) {
38 int v = e[i].to;
39 if (v == fa) continue;
40 dfs(v, u);
41 LL t = f[v] - e[i].w;
42 if (t > mx1) mx2 = mx1, mx1 = t;
43 else if (t > mx2) mx2 = t;
44 if (f[v] > e[i].w) f[u] = max(f[u], f[v] - e[i].w + w[u]);
45 }
46 Ans = max(Ans, f[u]);
47 Ans = max(Ans, mx1 + mx2 + w[u]);
48 }
49
50 int main() {
51 int n = read();
52 for (int i = 1; i <= n; ++i) w[i] = read();
53 for (int i = 1; i < n; ++i) {
54 int u = read(), v = read(), w = read();
55 add_edge(u, v, w);
56 }
57 dfs(1, 0);
58 cout << Ans;
59 return 0;
60 }
来源:oschina
链接:https://my.oschina.net/u/4408094/blog/3717947