題意:
有 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;
}