题意:
有 n 个城市,每个城市都有 wi 升油。如果两个城市之间有路,则通过这条路需要消耗 c 升。问从任意地方出发(边只经过一次),可以最多获得多少升油?
题解:
可以将题意转化为:在一棵树上求一条路径(所有点的权值和减去所有边的权值和最大)。
裸的树形dp,我们从第一个点出发进行 dfs,用 dp[i] 记录第 i 个点的权值最大,从儿子节点到父亲节点的权值取最优。即:
dp[u] = max(dp[u], dp[u] + dp[v] - c) 。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <bitset>
#include <stack>
#include <cmath>
#include <deque>
#include <queue>
#include <list>
#include <set>
#include <map>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define line printf("---------------------------\n")
#define mem(a, b) memset(a, b, sizeof(a))
#define mp make_pair
#define pi acos(-1)
using namespace std;
typedef long long ll;
const double eps = 1e-9;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
const int maxn = 300000+10;
ll val[maxn], dp[maxn];
vector<pair<ll, ll> > mapp[maxn];
ll ans;
void dfs(int u, int fat) {
dp[u] = val[u];
ans = max(ans, dp[u]);
for(int i = 0; i < mapp[u].size(); i++) {
int v = mapp[u][i].first;
if(v != fat) {
dfs(v, u);
ans = max(ans, dp[u] + dp[v] - mapp[u][i].second);
dp[u] = max(dp[u], dp[v] + val[u] - mapp[u][i].second);
}
}
}
int main() {
ll n;
cin >> n;
ans = 0;
mem(dp, 0);
for(int i = 1; i <= n; i++) {
cin >> val[i];
}
for(int i = 0; i < n - 1; i++) {
ll u, v, c;
cin >> u >> v >> c;
mapp[u].push_back(mp(v, c));
mapp[v].push_back(mp(u, c));
}
dfs(1, 0);
cout << ans << endl;
}