Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path

Posted heyuhhh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path相关的知识,希望对你有一定的参考价值。

D. The Fair Nut and the Best Path

题目链接https://codeforces.com/contest/1084/problem/D

题意:

给出一棵树,走不重复的路径,每到一个结点加上其权值,经过一条边减去其权值,路径中途减去后不能出现负数,问怎么选择路径可以让最后得到的最大。

 

题解:

这题考虑用dp来做。

我们定义dp[u]为走到u点的最大值,注意这里的方向,是走到u点。题目中的意思是路径不能走回头路。

对于一个父节点u,那么我们可以根据走到其儿子结点的最大值来更新经过父节点的路径的最大值。

如果两个儿子到u(dp[v1]+dp[v2]-dis(v1,u)-dis(v2,u))都为正数,那么此时ans = a[u]+dp[v1]+dp[v2]-dis(v1,u)-dis(v2,u)。在这里虽然dp指的是走到当前结点的最大值,但是反过来走并不影响其结果。

具体做法就是每次根据其儿子维护经过当前结点的最大值,在最后根据其儿子选择一个较大值更新当前结点的dp值。

这题要用大最大连续子段和的技巧...

 

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5+5;
int n;
ll a[N],dp[N];
ll ans;
vector <pair<int,int> > g[N];
void dfs(int node,int pa){
    ans=max(ans,a[node]);
    ll mx=0;
    for(auto v:g[node]){
        if(v.first==pa) continue ;
        dfs(v.first,node);
        ans=max(ans,mx+dp[v.first]-v.second+a[node]);
        mx=max(mx,dp[v.first]-v.second);
    }
    dp[node]=mx+a[node];
    return ;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%I64d",&a[i]);
    }
    for(int i=1;i<n;i++){
        int u,v,c;
        scanf("%d%d%d",&u,&v,&c);
        g[u].push_back(make_pair(v,c));
        g[v].push_back(make_pair(u,c));
    }
    dfs(1,-1);
    cout<<ans<<endl;
    return 0;
}

 

以上是关于Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #526 (Div. 2) E. The Fair Nut and Strings

Codeforces Round #526 (Div. 2) C. The Fair Nut and String

Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path

Codeforces Round #526 C - The Fair Nut and String /// 组合递推

CF1083(Round #526 Div. 1) 简要题解

Codeforces Round #436 E. Fire(背包dp+输出路径)