【题解】洛谷 P2052 [NOI2011] 道路修建

链接:洛谷

观察到该图有 n 个节点, n1 条边,可以发现它是一棵树。

考虑对它进行 dfs,求出对于每一个节点 u,它的子树的节点数量,记为 cntu。由题意,边 (u,v)u 在树上的深度小于 v)的费用应该是根节点到 u 的这条链上的节点个数,与以 v 为根的子树的节点数的差的绝对值。不难得出,根节点到 u 的链上的节点个数为: cnt1cntv,以 v 为根的子树的节点数为 cntv,所以边 (u,v) 的费用的表达式:

cost(u,v)=abs(cnt1cntvcntv)×w(u,v)=abs(ncntvcntv)×w(u,v)=abs(n2×cntv)×w(u,v)

在 dfs 的过程中计算即可。

注意:无向图,开 long long,取绝对值用 llabs

#include <bits/stdc++.h>
using namespace std;
namespace Prulystic { void Main(); }
int main(){
    Prulystic::Main();
    return 0;
}
namespace Prulystic{
    using ll = long long;
    using pll = pair<ll, ll>;
    const int N = 2e6 + 5;
    ll n, ans, son[N];
    vector<pll> g[N];
    inline void read(ll& x){
        ll s = 0, w = 1; char ch = getchar();
        while(ch < '0' || ch > '9') { w = (ch == '-' ? -1 : w); ch = getchar(); }
        while(ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar(); }
        x = s * w;
        return;
    }
    inline void write(ll x){
        if(x < 0) { x = -x; putchar('-'); }
        if(x > 9) write(x / 10);
        putchar(x % 10 + '0');
       return;
    }
    inline void write(ll x, char ch) { write(x); putchar(ch); }
    inline void add(ll a, ll b, ll c){
        g[a].push_back({b, c}), g[b].push_back({a, c});
        return;
    }
    void dfs(int u, int f){
        son[u] = 1;
        for(pll e : g[u]){
            ll v = e.first, w = e.second;
            if(v == f)
                continue;
            dfs(v, u);
            son[u] += son[v];
            ans += llabs(n - 2 * son[v]) * w;
        }
        return;
    }
    void Main(){
        read(n);
        for(int i = 1; i <= n - 1; i++){
            ll a, b, c; read(a), read(b), read(c);
            add(a, b, c);
        }
        dfs(1, 0);
        write(ans, '\n');
        return;
    }
}
posted @   Prülystic  阅读(0)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示