transaction transaction transaction
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 147 Accepted Submission(s): 67
As we know, the price of this book was different in each city. It is ai yuan in i t city. Kelukin will take taxi, whose price is 1 yuan per km and this fare cannot be ignored.
There are n−1 roads connecting n cities. Kelukin can choose any city to start his travel. He want to know the maximum money he can get.
For each test case:
first line contains an integer n ( 2≤n≤100000 ) means the number of cities;
second line contains n numbers, the i th number means the prices in i th city; (1≤Price≤10000)
then follows n−1 lines, each contains three numbers x , y and z which means there exists a road between x and y , the distance is z km (1≤z≤1000) .
1 4 10 40 15 30 1 2 30 1 3 2 3 4 10
8
思路:也就是说找两个点,大的点减小的点再减中间路径权值,找最大值
我们就只需要考虑每个点到它的子树里的最大值,从叶子节点一直找到根节点就可以了
所以是一个状态的转移
1.在叶子节点u的时候,它的子树就是有它本身,所以它卖书的最小花费就是 val[u] ,而卖书的最大价值也是 val[u]
所以叶子节点的答案就是 最大卖价 - 最小花费 = 0
2.向上回溯到它的父亲节点 u ,此刻叶子节点是 v , u v 间的距离是 w ,那么如果在 u 点买书和卖书,最小话费和最大价值都是 val[u] ,所以就要从前状态找更小花费和更大价值,如果 u 点的花费 < v 点花费 + 路费 w,那么自然是在u点买划算一些,而卖书自然的话,如果 u 的价格 > v点价格 - 路费 w 的话,就应该在 u 点卖,因为 u 点要么做买书位置,要么做卖书位置, 或者都不做,都不做的时候答案不会更新。
3. dp[ i ] [ j ] 中 , i 表示某点下标, j = 1表示该点卖书的最大值,j = 0 表示该点买书的最小值,然后每次都把最小状态赋值给它,父亲节点就能通过儿子节点的状态完整整个子树里的最优解了。
dp[i][0] = min(dp[i][0],dp[v][0] + w); 表示该点更新为最小花费
dp[i][1] = max(dp[i][1],dp[v][1] - w); 表示该点更新为最大价值
有可能同时更新为 dp[v][0] + w,和 dp[v][1] - w,但是答案不会更新为更大,因为此时会减2次 w,但是这个状态是需要保留的,因为更上方的点,到达 v 点的时候距离都得多上这一条 w,所以它是没有错的
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
using namespace std;
#define maxn 100005
#define ll long long
#define mem(a,x) memset(a,x,sizeof(a))
const ll inf = (1ll) << 60;
struct node{
int v,w;
node(int v_,int w_) : v(v_),w(w_){}
};
int dp[maxn][2];
int val[maxn];
vector<node>vec[maxn];
int n,ans;
void add(int u,int v,int w){
vec[u].push_back(node(v,w));
}
void treedp(int u,int pre){
dp[u][0] = dp[u][1] = val[u];
int sz = vec[u].size();
for(int i = 0;i < sz;i++){
int v = vec[u][i].v;
int w = vec[u][i].w;
if(v == pre)
continue;
treedp(v,u);
dp[u][0] = min(dp[u][0],dp[v][0] + w);
dp[u][1] = max(dp[u][1],dp[v][1] - w);
}
ans = max(ans,dp[u][1] - dp[u][0]);
}
int main(){
int u,v,w,t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i = 1;i <= n;i++){
scanf("%d",&val[i]);
vec[i].clear();
}
for(int i = 1;i < n;i++){
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
ans = 0;
treedp(1,-1);
printf("%d\n",ans);
}
}