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

 

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