码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-12-13 21:46:39      阅读:279      评论:0      收藏:0      [点我收藏+]

标签:back   target   col   air   bsp   一个   nod   name   dfs   

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

标签:back   target   col   air   bsp   一个   nod   name   dfs   

原文地址:https://www.cnblogs.com/heyuhhh/p/10116517.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!