2017 ACM/ICPC Asia Regional Shenyang Online transaction transaction transaction
题目大意:
多组样例,每组输入一棵树,然后书上每个节点有权值,每两个点之间的边有权值,任选两个点,然后让你求这两个点的差值再减去这两点之间的变得权值的最大值;
基本思路:
树型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\n",res); } }