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;
}

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

时间: 2024-08-30 13:44:51

Codeforces Round #526 (Div. 2) D. The Fair Nut and the Best Path的相关文章

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

C. The Fair Nut and String 题目链接:https://codeforces.com/contest/1084/problem/C 题意: 给出一个字符串,找出都为a的子序列(比如ai,aj,ak)满足以下条件的个数: 1.子序列的索引单增(i<j<k): 2.在原字符串中,若ai=aj=ak=a,那么满足i<=k1<j,j<=k2<k 并且 ak1=ak2=b. 通俗点说,就是找这样的子序列个数:要么单个a,要么每个a之间都有一个b. 题解:

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

E. The Fair Nut and Strings 题目链接:https://codeforces.com/contest/1084/problem/E 题意: 输入n,k,k代表一共有长度为n的多少个字符串.然后给出一个最小字符串s,最大字符串t,满足对于所有的k个字符串有s<=S<=t. 最后求满足条件的k个字符串(自己构造)的不同前缀数量的和. 题解: 这题很巧妙,设dp(i)表示长度为i的前缀的数量和,一开始有dp(1)=0. 后来随着长度的增加,我们每次可以在最后加一个a或者b,

Codeforces Round #526 (Div. 1)

毕竟是上紫之后的第一场div1,还是太菜了啊,看来我要滚回去打div2了. A. The Fair Nut and the Best Path 这题本来是傻逼贪心dfs,结果我越写越麻烦,然后就只有150了.. #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<set> #include<map> #include<ve

Codeforces Round #485 (Div. 2) D. Fair

Codeforces Round #485 (Div. 2) D. Fair 题目连接: http://codeforces.com/contest/987/problem/D Description Some company is going to hold a fair in Byteland. There are $n$ towns in Byteland and $m$ two-way roads between towns. Of course, you can reach any t

Codeforces Round #436 (Div. 2)【A、B、C、D、E】

Codeforces Round #436 (Div. 2) 敲出一身冷汗...感觉自己宛如智障:( codeforces 864 A. Fair Game[水] 题意:已知n为偶数,有n张卡片,每张卡片上都写有一个数,两个人每人选一个数,每人可以拿的卡片必须写有是自己选的数,问能否选择两个数使得两个人每人拿的卡片数一样多并且能拿光卡片.[就是看输入是不是只有两种数字] //:第一遍我看成字符串包含有选的数字也能拿,,这样写着居然过了..水题水题.. 1 #include<cstdio> 2

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd