首页 > 其他分享 >旅行

旅行

时间:2022-09-25 15:26:02浏览次数:66  
标签:旅行 10 int 路径 leq 能量 d1

旅行

给定一个 $n$ 个节点的树,节点编号为 $1 \sim n$。

请你从中选择一个简单路径(不能包含重复节点或重复的边),并沿所选路径来一场旅行,更具体的说,就是从所选路径的一个端点沿路径前往另一个端点。

注意,所选简单路径可以只由一个节点组成。

旅行需要花费能量。

初始时,你的能量为 $0$。

在旅行过程中:

  • 在经过任何一条边之前,你的现有能量都不能少于该边所需消耗的能量(否则,将无法顺利通过该边)。
  • 在满足条件 $1$ 的前提下,旅行结束时,剩余的能量尽可能大。

请计算并输出剩余能量的最大可能值。

输入格式

第一行包含整数 $n$。

第二行包含 $n$ 个整数 $w_1,w_2, \dots ,w_n$。

接下来 $n−1$ 行,每行包含三个整数 $u,v,c$,表示存在一条边 $(u,v)$,经过它所需的能量为 $c$。

保证给定图是一棵树。

输出格式

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

数据范围

前 $3$ 个测试点满足 $1 \leq n \leq 5$。
所有测试点满足 $1 \leq n \leq 3 \times {10}^{5}$,$0 \leq w_i \leq {10}^{9}$,$1 \leq u,v \leq n$,$u \ne v$,$1 \leq c \leq {10}^{9}$。

输入样例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

 

解题思路

  比赛的时候没细想,然后蒙对了做法。

  如果不考虑第一个条件,这个问题就变得很简单,就是找一条权值最大的路径,类似于求树的直径。现在我先不考虑这个条件,直接求权值最大的路径,然后看一下可不可以证明这个最大路径一定是满足这个约束条件的,如果满足这个条件意味着我们可以忽略这个约束条件直接求就可以了。

  可以发现把这段能量为负的部分去掉,整个路径只留后半段,结果一定会比保留这部分的要优。因此如果存在走完某条路径能量变负数,意味着这个路径一定不是最优解,因为我们可以构造出能量更大的路径。因此最优解一定满足在中间任意时刻总能量都是大于等于$0$的。

  所以可以用树形dp来求出一条权值最大的路径。

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 3e5 + 10, M = N * 2;
 7 
 8 int head[N], e[M], wts[M], ne[M], idx;
 9 int w[N];
10 LL f[N];
11 LL ans;
12 
13 void add(int v, int w, int wt) {
14     e[idx] = w, wts[idx] = wt, ne[idx] = head[v], head[v] = idx++;
15 }
16 
17 void dfs(int u, int pre) {
18     LL d1 = 0, d2 = 0;
19     for (int i = head[u]; i != -1; i = ne[i]) {
20         if (e[i] != pre) {
21             dfs(e[i], u);
22             LL t = f[e[i]] - wts[i];
23             if (t >= d1) d2 = d1, d1 = t;
24             else if (t >= d2) d2 = t;
25         }
26     }
27     
28     f[u] = d1 + w[u];
29     ans = max(ans, d1 + d2 + w[u]);
30 }
31 
32 int main() {
33     int n;
34     scanf("%d", &n);
35     for (int i = 1; i <= n; i++) {
36         scanf("%d", w + i);
37     }
38     memset(head, -1, sizeof(head));
39     for (int i = 0; i < n - 1; i++) {
40         int v, w, wt;
41         scanf("%d %d %d", &v, &w, &wt);
42         add(v, w, wt), add(w, v, wt);
43     }
44     
45     dfs(1, -1);
46     printf("%lld", ans);
47     
48     return 0;
49 }

 

参考资料

  AcWing 4620. 旅行(AcWing杯 - 周赛):https://www.acwing.com/video/4404/

标签:旅行,10,int,路径,leq,能量,d1
From: https://www.cnblogs.com/onlyblues/p/16727896.html

相关文章

  • DFS求旅行商问题
    设有城市1.2.3.4,求从1出发,不重复地经过4个城市且最终返回城市1的最短路径问题分析:将该题转为加权图模型,尝试所有可行路线,并比较得出最短路径。#include<iostream>#defi......
  • 旅行问题
    单调队列优化DP原题链接题目描述:给定一个环,环上每个节点有一个油量,当车开到这个节点时可以获得该点的油量,该点还有一个值di表示车从i点开到i+1点所耗费的油量,现有一辆......
  • I [NOIP2012]开车旅行 每次往第一或者第二近的点走,求最大比值 倍增算法 set
    链接:https://ac.nowcoder.com/acm/problem/16562来源:牛客网题目描述小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较......
  • P1081 [NOIP2012 提高组] 开车旅行
    记城市\(i\)的海拔高度为\(h_i\),\(i\)和\(j\)之间的距离\(d_{i,j}=|h_i-h_j|\)。旅行过程中,两人轮流开车,第一天\(A\)开车,之后每天轮换一次。选择一个城市\(s\)......
  • 「HNOI2019」校园旅行
    将相邻且颜色相同的点视作一个连通块,若该连通块是二分图,那么从连通块中一点\(x\)到连通块中一点\(y\)的路径的奇偶性确定所以对于块外一点\(x\)到块内一点\(y\),可以将它们......
  • 1026 [NOIP2001]Car的旅行路线 标点建图 勾股定理 floyd
     链接:https://ac.nowcoder.com/acm/contest/26077/1026来源:牛客网题目描述又到暑假了,住在城市A的Car想和朋友一起去城市B旅游。她知道每个......
  • 暑假集训五[星际旅行, 砍树, 超级树, 求和]
    暑假集训5星际旅行这个题刚看我觉得很ex,没事思路,就跳了,然后就去欺负\(T4\)了后来别的不会做,然后回来肝它...就肝出来了...对了,注意开\(longlong\)首先转化一下题意,我......
  • 牛的旅行
    P1522[USACO2.4]牛的旅行CowTours-洛谷|计算机科学教育新生态(luogu.com.cn)dfs为图中的连通块染色floyd求出任意两点的最短距离,不连通就INF求出每个连通块中......