AcWing 4620. 旅行 树形DP,记忆化搜索

题目描述

给定一个 n 个节点的树,节点编号为 1∼n。

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

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

旅行需要花费能量。

初始时,你的能量为 0。

在旅行过程中:

  • 每经过一个节点(包括起点和终点),就可以得到该节点的能量,其中节点 i 包含的能量为 wi。
  • 每经过一条边 (u,v),就需要消耗一定的能量 c。
    你设计的旅行路线应满足:

在经过任何一条边之前,你的现有能量都不能少于该边所需消耗的能量(否则,将无法顺利通过该边)。
在满足条件 1 的前提下,旅行结束时,剩余的能量尽可能大。
请计算并输出剩余能量的最大可能值。
输入格式
第一行包含整数 n。

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

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

保证给定图是一棵树。

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

数据范围
前 3 个测试点满足 1≤n≤5。
所有测试点满足 1≤n≤3×105,0≤wi≤109,1≤u,v≤n,u≠v,1≤c≤109。

输入样例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的限制,还能转化成求树的直径的问题吗?

我们现在想一下,在求树的直径的过程中,会经过权值为负数的点嘛?
显然是不会的,那么我们在遍历的过程中,遇到负数的情况,直接跳过就行了。

yxc那个解释我听不明白,他说的去掉,我感觉只是代码上的等价,因为那段代码去掉之后,确实不影响正确性。

出题人就是有可能给你加一个多余的限制条件来阻碍你的思维,但是其实这个条件是没有用的。这就是和别人差距的地方。

时间复杂度

代码

#include <iostream>
#include <cstring>

using namespace std;

typedef long long LL;

const int N = 300010, M = N << 1;

int n;
int v[N];
int h[N], e[M], ne[M], w[M], idx;
LL f[N]; // 到达N剩余的最大能量
LL ans;

void add(int a, int b, int c) {
    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
}

void dfs(int u, int fa) {
    
    LL max1 = 0, max2 = 0;
    
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (j == fa) continue;
        // 求子节点的, 这个很关键。
        dfs(j, u);
        
        // 这个去掉也是可以的
        // if (f[j] - w[i] < 0) continue;
        // 更新最大值
        if (f[j] - w[i] >= max1) {
            max2 = max1;
            max1 = f[j] - w[i];
        }
        // 更新次大值
        else if (f[j] - w[i] > max2) {
            max2 = f[j] - w[i];
        }
    }
    
    // 更新全局ans
    ans = max(ans, v[u] + max1 + max2);
    // f[u] 只会计算一次。
    f[u] = v[u] + max1;
}

int main() {
    cin >> n;
    memset(h, -1, sizeof h);
    
    for (int i = 1; i <= n ; i ++ ) scanf("%d", &v[i]);
    
    for (int i = 1; i < n; i ++ ) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
        add(b, a, c);
    }
    
    dfs(1, -1);
    
    cout << ans << endl;
    
    return 0;
}


很抱歉,我无法直接为您提供完整的协议栈代码。协议栈的实现可能因硬件和操作系统不同而有所不同,需要根据具体情况进行适当的修改。 以下是一些常用协议栈的简介及其相关资源,供您参考: 1. WIFI协议栈:WIFI协议栈主要包括PHY层、MAC层和网络层。常用的WIFI协议包括IEEE 802.11a/b/g/n/ac/ax等。如果您需要实现WIFI协议栈,您可以参考以下资源: - ESP8266 WIFI模块源代码:https://github.com/espressif/esp8266-rtos-sdk/tree/master/components/esp8266/include/driver/include/driver - ESP32 WIFI模块源代码:https://github.com/espressif/esp-idf/tree/master/components/esp_wifi - Linux下的WIFI实现:https://wireless.wiki.kernel.org/en/developers/documentation/wireless-drivers 2. 蓝牙协议栈蓝牙协议栈主要包括PHY层、MAC层、L2CAP层、RFCOMM层、SDP层等。常用的蓝牙协议包括BLE、Classic Bluetooth等。如果您需要实现蓝牙协议栈,您可以参考以下资源: - BlueZ蓝牙协议栈:https://git.kernel.org/pub/scm/bluetooth/bluez.git/ - Android蓝牙协议栈:https://android.googlesource.com/platform/system/bt/ - Nordic Semiconductor的nRF5 SDK:https://www.nordicsemi.com/Software-and-Tools/Software/nRF5-SDK 3. TCP/IP协议栈:TCP/IP协议栈主要包括物理层、数据链路层、网络层、传输层和应用层。常用的TCP/IP协议包括TCP、UDP、IP等。如果您需要实现TCP/IP协议栈,您可以参考以下资源: - lwIP协议栈:http://www.nongnu.org/lwip/ - Linux内核中的TCP/IP协议栈实现:https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt - Contiki OS中的TCP/IP协议栈实现:https://github.com/contiki-os/contiki/tree/master/os/net 4. CoAP协议栈:CoAP协议栈是一种轻量级的RESTful协议,适用于物联网设备之间的通信。如果您需要实现CoAP协议栈,您可以参考以下资源: - Erbium CoAP协议栈:https://github.com/contiki-os/er-coap - LibCoAP协议栈:https://github.com/obgm/libcoap - Californium CoAP协议栈:https://github.com/eclipse/californium 5. MQTT协议栈:MQTT协议栈是一种轻量级的消息协议,适用于物联网设备之间的通信。如果您需要实现MQTT协议栈,您可以参考以下资源: - Paho MQTT协议栈:https://github.com/eclipse/paho.mqtt.embedded-c - Mosquitto MQTT协议栈:https://github.com/eclipse/mosquitto - Eclipse IoT MQTT协议栈:https://www.eclipse.org/paho/clients/c/embedded/ 6. HTTP(S)协议栈:HTTP(S)协议栈是一种广泛应用于互联网上的应用层协议。如果您需要实现HTTP(S)协议栈,您可以参考以下资源: - Mongoose HTTP(S)协议栈:https://github.com/cesanta/mongoose - libcurl HTTP(S)协议栈:https://curl.se/libcurl/ - Microchip HTTP(S)协议栈:https://www.microchip.com/design-centers/wireless-connectivity/wifi/products/wi-fi-software/mrf24w-software 7. SSL/TLS协议栈:SSL/TLS协议栈是一种安全传输协议,适用于互联网上的安全通信。如果您需要实现SSL/TLS协议栈,您可以参考以下资源: - OpenSSL SSL/TLS协议栈:https://www.openssl.org/ - wolfSSL SSL/TLS协议栈:https://www.wolfssl.com/ - mbed TLS SSL/TLS协议栈:https://tls.mbed.org/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值