InputThe first line contains an integer TT (1≤T≤101≤T≤10) , the number of test cases.
For each test case:
first line contains an integer nn (2≤n≤1000002≤n≤100000) means the number of cities;
second line contains nn numbers, the iithth number means the prices in iithth city; (1≤Price≤10000)(1≤Price≤10000)
then follows n−1n−1 lines, each contains three numbers xx, yy and zz which means there exists a road between xx and yy, the distance is zzkmkm (1≤z≤1000)(1≤z≤1000).
OutputFor each test case, output a single number in a line: the maximum money he can get.
Sample Inputnode
1 4 10 40 15 30 1 2 30 1 3 2 3 4 10
Sample Outputc++
8
一我的在任意点买书(消费点权),通过边(花费边权),在任意点卖书(收获点权),求最大收益。
树形结构,由于父子关系未知,因此双向建边。
dp[i][0]表示i子树中的最少买书消费,dp[i][1]表示i子树中的最大卖书收益,
dp[i][0]+dp[i][1]表示以i为最近公共父节点的最大收益,最优解并不是根节点,所以ans须要不断更新。
#include<bits/stdc++.h> #define MAX 100005 #define INF 0x3f3f3f3f using namespace std; typedef long long ll; int a[MAX]; int dp[MAX][2]; int ans; struct Node{ int v,w; }node; vector<Node> v[MAX]; void dfs(int x,int pre){ dp[x][0]=-a[x];dp[x][1]=a[x]; for(int i=0;i<v[x].size();i++){ int to=v[x][i].v; if(to==pre) continue; int w=v[x][i].w; dfs(to,x); dp[x][0]=max(dp[x][0],dp[to][0]-w); dp[x][1]=max(dp[x][1],dp[to][1]-w); } ans=max(ans,dp[x][0]+dp[x][1]); //不断更新 } int main() { int t,n,i; int x,y,w; scanf("%d",&t); while(t--){ scanf("%d",&n); for(i=1;i<=n;i++){ scanf("%d",&a[i]); v[i].clear(); } for(i=1;i<n;i++){ scanf("%d%d%d",&x,&y,&w); node.v=y;node.w=w; v[x].push_back(node); node.v=x; v[y].push_back(node); } ans=-INF; dfs(1,-1); printf("%d\n",ans); } return 0; }