[ZJOI2007]时态同步

题意

Here

思考

这个题过于水…

考虑单独的以 \(u\) 为根的一个子树,我们假设 \(u\) 的所有子节点 \(v\) 形成的子树已经满足条件(即 \(v\)\(v\) 的叶子节点的距离经过 \(f[v]\) 次改变已经达到了深度相等的状态),我们现在只需改变所有 \(e\{u, v\}\) 的值使得 \(u\) 子树的所有叶子节点深度相同,很显然,是让所有深度最小的叶子节点变成深度最大的叶子节点即可,当前改变的总代价就是 \(\sum (MAX-d[v]) + \sum f[v]\)\(MAX\) 为最深叶子节点的深度。

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 500050;
typedef long long ll;
struct node{
    ll nxt, to, dis;
}edge[N << 1];
ll head[N], num;
void build(ll from, ll to, ll dis){
    edge[++num].nxt = head[from];
    edge[num].to = to;
    edge[num].dis = dis;
    head[from] = num;
}
ll f[N], MAX[N];
void dfs(ll u, ll fa){
    vector<int> G; f[u] = 0; MAX[u] = 0;
    for(ll i=head[u]; i; i=edge[i].nxt){
        ll v = edge[i].to, d = edge[i].dis;
        if(v == fa) continue;
        dfs(v, u);
        G.push_back(MAX[v] + d);
        MAX[u] = max(MAX[v] + d, MAX[u]);
        f[u] += f[v];
    }
    for(int x : G){
        f[u] += MAX[u] - x;
    }
}
ll n, s;
int main(){
    cin >> n >> s;
    for(ll i=1; i<=n-1; i++){
        ll u, v, d; cin >> u >> v >> d;
        build(u, v, d); build(v, u, d);
    }
    dfs(s, 0);
    cout << f[s];
    return 0;
}

总结

写完记得随便造组数据查一下…不然后果有可能是第一遍全 \(WA\)

posted @ 2018-12-03 20:38  alecli  阅读(82)  评论(0编辑  收藏  举报