题目大意:
多组样例,每组输入一棵树,然后书上每个节点有权值,每两个点之间的边有权值,任选两个点,然后让你求这两个点的差值再减去这两点之间的变得权值的最大值;
基本思路:
树型dp,以1节点为根,dfs其子节点,用dmax[k]表示以k节点为根的子树中所能卖的最大价格,dmin[k]表示买书花费的最少价格,ans=max(dmax[k]-dmin[k])。边的花费加到dmax和dmin里面就行。
反思与总结:
蒟蒻只能先到最朴素的超时解法,这个思路真的很难想我觉得;
代码如下:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 100000+10;
typedef long long ll;
struct Node
{
int v,w,next;
}node[maxn*2];
int head[maxn];
bool vis[maxn];
int dmax[maxn],dmin[maxn],ans[maxn];
int res;
int cnt;
void addEdge(int u,int v,int w)
{
node[cnt].v=v;
node[cnt].w=w;
node[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(int idx)
{
vis[idx]=1;
dmax[idx]=dmin[idx]=ans[idx];
int v,w;
for(int i=head[idx];i!=-1;i=node[i].next)
{
v=node[i].v;
w=node[i].w;
if(vis[v]) continue;
dfs(v);
dmax[idx]=max(dmax[idx],dmax[v]-w);
dmin[idx]=min(dmin[idx],dmin[v]+w);
res=max(res,dmax[idx]-dmin[idx]);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
res=-0x3f3f3f3f;
cnt=0;
memset(head,-1,sizeof(head));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++) scanf("%d",&ans[i]);
for(int i=1;i<=n-1;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addEdge(u,v,w);
addEdge(v,u,w);
}
dfs(1);
printf("%d
",res);
}
}