1 solutions

  • 0
    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;  // 防止损伤值总和溢出,使用长整型
    const int MAXN = 1e6 + 5;  // 最大节点数,适配n≤1e6的测试点
    
    vector<pair<int, int>> adj[MAXN];  // 无向邻接表:存储(相邻节点, 脆弱值)
    ll ans = 0;  // 所有通信管道的总损伤值
    int n;       // 树的总节点数(用户数量)
    
    // 迭代DFS函数:计算子树大小并累加损伤值(避免递归栈溢出)
    void iterative_dfs() {
        // 栈元素:(当前节点u, 父节点parent, 是否已处理子节点)
        stack<tuple<int, int, bool>> stk;
        stk.emplace(1, -1, false);  // 根节点1,父节点-1(无父节点),初始未处理
    
        int sub_size[MAXN] = {0};  // 记录每个节点为根的子树大小
    
        while (!stk.empty()) {
            // 手动拆解栈顶的三元组(兼容C++14,替代结构化绑定)
            tuple<int, int, bool> top = stk.top();
            stk.pop();
            int u = get<0>(top);      // 当前节点
            int parent = get<1>(top); // 当前节点的父节点
            bool is_processed = get<2>(top);  // 是否已处理子节点
    
            if (!is_processed) {
                // 第一步:标记为“待处理”后重新入栈,后续处理子节点
                stk.emplace(u, parent, true);
                // 逆序遍历邻接边(保证子节点处理顺序与递归一致)
                for (auto it = adj[u].rbegin(); it != adj[u].rend(); ++it) {
                    int v = it->first;  // 邻接节点v
                    if (v != parent) {  // 跳过父节点,只处理子节点
                        stk.emplace(v, u, false);
                    }
                }
            } else {
                // 第二步:所有子节点已处理,计算当前节点的子树大小和损伤值
                sub_size[u] = 1;  // 子树大小初始为1(当前节点自身)
                for (auto &edge : adj[u]) {
                    int v = edge.first;   // 子节点v
                    int c = edge.second;  // 边u-v的脆弱值
                    if (v != parent) {    // v是子节点(非父节点)
                        sub_size[u] += sub_size[v];  // 累加子树大小
                        // 计算边的损伤值:|n - 2*子树大小| × 脆弱值
                        ans += (ll)abs(n - 2 * sub_size[v]) * c;
                    }
                }
            }
        }
    }
    
    int main() {
        // 输入优化:关闭cin与stdio同步,加速输入
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        cin >> n;  // 读取节点总数
        // 读取n-1条边,构建无向邻接表
        for (int i = 0; i < n - 1; ++i) {
            int a, b, c;
            cin >> a >> b >> c;
            adj[a].emplace_back(b, c);
            adj[b].emplace_back(a, c);
        }
    
        iterative_dfs();  // 计算子树大小并累加损伤值
        cout << ans << endl;  // 输出总损伤值
        return 0;
    }
    

    Information

    ID
    1602
    Time
    2000ms
    Memory
    256MiB
    Difficulty
    7
    Tags
    (None)
    # Submissions
    61
    Accepted
    12
    Uploaded By