树的直径

一个国家由n 个城市组成,这 n 个城市由 n−1 条双向道路连接,呈一个树形结构。

每个城市都设有加油站,在第 i 个城市可以购买 wi升汽油。

汽车在道路上行驶,毫无疑问也会消耗汽油,每条道路的具体耗油量也会给出。

现在,需要制定一条汽车的行进路线,从任意城市 s出发,经过一条简单路径,到达任意城市 e 结束。

注意,行进路线也可以只包含一个城市(也就是哪都没去)。

汽车初始时油箱是空的,但是可以在路线中经过的每个城市购买汽油,包括开始城市和最终城市。

如果在一条行进路线中,汽车沿一条道路从某一城市开往另一城市时,现有油量小于该条道路所需油量,那么就说明这条行进路线行不通。

请问,在保证行进路线合理的情况下,汽车在抵达最终城市后,可以剩余的最大油量是多少?

再次提醒,汽车在最终城市也可以加油。

输入格式

第一行包含整数 n。

第二行包含 n 个整数 w1,w2,,wn

接下来 n1 行,每行包含三个整数 u,v,c,表示城市 u 和城市 v 之间存在一条双向道路,耗油量为 c。

输出格式

一个整数,表示可能的最大剩余油量。

数据范围

前三个测试点满足,1n5
所有测试点满足,1n3×10^50wi10^91u,vn1c10^9uv

输入样例1:

3
1 3 3
1 2 2
1 3 2

输出样例1:

3

输入样例2:

5
6 3 2 5 0
1 2 10
2 3 3
2 4 1
1 5 1

输出样例2:

7
遍历路径的最高点,从上到下遍历,携带两个参数,当前节点和父节点,以免重复搜索,并且把ans定义为全局变量,这样在遍历时即可求出答案,此树的节点是正权值,边是负权值
#include <iostream>
#include <cstring>
#include <algorithm>
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 300010,M=2*N;
int h[N], e[M], ne[M], idx,w[M];
int v[N];
//LL dp[N];
LL ans=0;
void add(int a, int b, int c)  // 添加一条边a->b,边权为c
{
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
LL dfs(int u,int father){
    LL d1=0,d2=0;
    for(int i=h[u];~i;i=ne[i]){
        int j=e[i];
        if(j==father)continue;
         LL res=dfs(j,u);
        if(res<w[i])continue;
        res-=w[i];
        if(res>=d1)d2=d1,d1=res;
        else if(res>d2)d2=res;
    }
    ans=max(ans,d1+d2+v[u]);
    return d1+v[u];
}
int main()
{
    int n;
    scanf("%d", &n);
    memset(h, -1, sizeof h);
    for (int i = 1; i <= n; i ++ ) scanf("%d", &v[i]);
    for (int k = 0; k < n-1; k ++ ){
        int a,b,c;
        scanf("%d%d%d", &a,&b,&c);
        add(a, b, c);
        add(b, a, c);
    }
    dfs(1,-1);
    cout<<ans;
    return 0;
}

 

 
posted @ 2021-10-17 20:12  兮何其  阅读(31)  评论(0)    收藏  举报