CodeForces - 1084D(樹形dp)

題意:

有 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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章