Codeforces Round #526 D - The Fair Nut and the Best Path /// 树上两点间路径花费

题目大意:

给定一棵树 树上每个点有对应的点权

树上每条边有对应的边权

经过一个点可得到点权 经过一条边必须花费边权

即从u到v 最终得分=u的点权-u到v的边权+v的点权

求树上一条路径使得得分最大

看注释

#include <bits/stdc++.h>
#define LL long long
#define INf 0x3f3f3f3f
using namespace std;
const int N=3e5+5;
bool vis[N];
LL w[N], ans;
int n;
struct NODE { int to,nt; LL l; }e[N<<1];
int head[N], tot;
void addE(int u,int v,LL l) {
    e[tot].to=v, e[tot].l=l;
    e[tot].nt=head[u];
    head[u]=tot++;
}
void init() {
    memset(head,0,sizeof(head));
    tot=1;
}
LL dfs(int u,int fa) {
    vis[u]=1;
    LL ans1=0LL, ans2=0LL; 
    // ans1由子节点出发的一条路径最大得分 ans2为次大
    for(int i=head[u];i;i=e[i].nt) {
        int v=e[i].to;
        if(v==fa || vis[v]) continue;
        LL tmp=dfs(v,u)-e[i].l;
        if(tmp>ans1) swap(tmp,ans1); 
        if(tmp>ans2) swap(tmp,ans2);
    }
    ans=max(ans,ans1+ans2+w[u]);
    // 可由最大得分和次大得分加上u点 得到一条经过u点的路径的最大得分
    return ans1+w[u]; // 只返回由u出发的一条路径可得到的最大得分
}
int main()
{
    while(~scanf("%d",&n)) {
        for(int i=1;i<=n;i++) scanf("%I64d",&w[i]);
        init();
        for(int i=1;i<n;i++) {
            int u,v; LL l;
            scanf("%d%d%I64d",&u,&v,&l);
            addE(u,v,l); addE(v,u,l);
        }
        memset(vis,0,sizeof(vis));
        ans=0LL;
        dfs(1,0);
        printf("%I64d\n",ans);
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zquzjx/p/10104350.html