【Codeforces 1083A】The Fair Nut and the Best Path

【链接】 我是链接,点我呀:)
【题意】


题意

【题解】


我们最后要的是一条最长的路径。
这条路径的权值和是所有点的权值和-所有边的权值和且这个值最大。
显然如果我们在某一条边上的累计的权值和<0了,那么我们会发现,我们完全没有必要一直累加到这条边,直接从边的另外一个端点开始重新累加更好(这时累加和>=0)
所以如果我们求的是最大的权值和-边权和的话,那么求出来的路径一定不会有中间某个地方走着走着没油的情况
因此我们只要按照树上最长链的类似方法。
求出来,从i的不同子树下的节点到达i节点的点权和减去边权和的最大值和次小值。
对于所有的点,用这两个值的和尝试更新答案即可。

【代码】

#include <bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 3e5;

int n;
int a[N+10];
ll f[N+10][2],ans=0;

vector<pair<int,int> > g[N+10];

void dfs(int x,int pre){
    int len = g[x].size();
    f[x][0] = a[x];
    for (int i = 0;i < len;i++){
        int y = g[x][i].first,cost = g[x][i].second;
        if (y==pre) continue;
        dfs(y,x);
        if (f[x][0]<f[y][0]-cost+a[x]){
            f[x][1] = f[x][0];
            f[x][0] = f[y][0]-cost+a[x];
        }else{
            if (f[x][1]<f[y][0]-cost+a[x]){
                f[x][1] = f[y][0]-cost+a[x];
            }
        }
    }
    if (f[x][1]>0){
        ans = max(ans,f[x][0]+f[x][1]-a[x]);
    }else ans = max(ans,f[x][0]);

}

int main(){
    ios::sync_with_stdio(0),cin.tie(0);
    cin >> n;
    for (int i = 1;i <= n;i++) cin >>a[i];
    for (int i = 1;i <= n-1;i++){
        int x,y,z;
        cin >> x >> y >> z;
        g[x].push_back({y,z});
        g[y].push_back({x,z});
    }
    dfs(1,-1);
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/AWCXV/p/10703062.html