2020Nowcode多校 Round9 B.Groundhog and Apple Tree

题意

给一棵树 初始\(hp=0\) 经过一条边会掉血\(w_{i}\) 第一次到达一个点可以回血\(a_{i}\) 在一个点休息\(1s\)可以回复\(1hp\) 血不能小于\(0\)
每条边最多经过两次 求从起点经过所有点再回到起点到最小时间

题解

休息的话干脆就在起点休息够了再出发吧
在分叉路口的时候走哪个方向是个问题
对于每一棵子树 可以维护出走这个方向的最小\(hp\) 和走回来还剩下的\(hp\)
那么可以根据这两个值的大小关系把子树分成两种 一种是走回来回的血比走之前掉的血还多 还有一种...
显然可以在第一种的选一个掉血最少的开始先走 走完之后还剩一些血
对于剩下的 比较一下谁先走更优

#include <bits/stdc++.h>
#include <stdio.h>
#include <iostream>
#include <set>
#include <string.h>
#include <string>
#include <map>
#include <vector>
using namespace std;
typedef long long ll;
const int mod = 998244353;
const int INF = 0x3f3f3f3f;
const int MAXN = 100005;

int n, cnt;
int a[MAXN];
struct node {
    int to, nex, val;
}E[MAXN << 1];
int head[MAXN];

struct ed {
    int id;
    ll cost, gain;
}dp[MAXN];

bool cmp(ed A, ed B) {
    if(A.gain > A.cost) {
        if(B.gain > B.cost) return A.cost < B.cost;
        else return true;
    } else {
        if(B.gain > B.cost) return false;
        else return A.gain > B.gain;
    }
}

void dfs(int x, int fa) {
    vector<ed> comp;
    for(int i = head[x]; i; i = E[i].nex) {
        int v = E[i].to;
        if(v == fa) continue;
        
        dfs(v, x);
        dp[v].id = v;
        dp[v].cost += E[i].val; 
        dp[v].gain -= E[i].val;
        if(dp[v].gain < 0) dp[v].cost -= dp[v].gain, dp[v].gain = 0;

        comp.push_back(dp[v]);
    }
    sort(comp.begin(), comp.end(), cmp);

    dp[x].cost = 0;
    ll now = a[x];
    for(int i = 0; i < comp.size(); i++) {
    
        ed v = comp[i];
        now -= v.cost;
        if(now < 0) {
            dp[x].cost += -now;
            now = 0;
        }
        now += v.gain;
    }
    dp[x].gain = now;
}

int main() {
    int T;
    cin>>T;
    while(T--) {
        cnt = 0;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) scanf("%d", &a[i]), head[i] = 0;

        for(int i = 1; i < n; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w);
            E[++cnt].to = v; E[cnt].nex = head[u]; head[u] = cnt; E[cnt].val = w;
            E[++cnt].to = u; E[cnt].nex = head[v]; head[v] = cnt; E[cnt].val = w;
        }
        dfs(1, 0);
        printf("%lld\n", dp[1].cost);
    }
    return 0;
}

posted @ 2020-08-09 00:59  lwqq3  阅读(220)  评论(0编辑  收藏  举报