首页 > 其他分享 >福建WC2014 路径权值(Kruskal重构树 + 树状数组)

福建WC2014 路径权值(Kruskal重构树 + 树状数组)

时间:2022-11-03 20:45:11浏览次数:56  
标签:std int siz Kruskal WC2014 权值 now leader

题目描述:

给定一个带权树,树上任意两点间的路径权值 \(d\left(x,y\right)\) 定义为 \(x,y\) 这两个点之间路径上的最小值,树上任意一点x的权值定义为这个点到树上其他所有点的路径权值和,即 \(\sum d\left(x,i\right)\),现求树上每一个点的路径权值和。

Input Format

首先输入一个整数 \(n\left(1 \leq n \leq 10^5 \right)\) ,表示树的点的个数。 
接下来 \(n−1\) 行,每行三个整数 \(x,y,s\left(1\leq x,y\leq n,1\leq s \leq 1000\right)\) ,表示编号为 \(x\) 的节点和编号为 \(y\) 的节点之间存在一条权值为 \(s\) 的边,树上每个点的编号为 \(1\sim n\)

Output Format

n行,每行输出每个节点对应的路径权值和

Sample Input

    4
    1 2 2
    2 4 1
    2 3 1

Sample Output

    4
    4
    3
    3

思路:

    #include <bits/stdc++.h>

    using i64 = long long;

    #define rep(i,a,b) for (int i = a; i < b; i++)
    #define per(i,a,b) for (int i = a; i >= b; i--)
    #define SZ(s) int(s.size())
    #define all(v) v.begin(), v.end()

    template <typename T>
    struct Fenwick {
        const int n;
        std::vector<T> tr;
        Fenwick(int n) : n(n), tr(n + 1) {}

        void add(int x, T v) {
            for (int i = x; i <= n; i += i & -i) 
                tr[i] += v;
        }

        T sum(int x) {
            T ans = 0;
            for (int i = x; i; i-=i&-i) ans += tr[i];
            return ans;
        }
        
        T rangeSum(int l, int r) {return sum(r) - sum(l);}
        
        int query(T s) { // 查询1~pos的和小于等于s
            int pos = 0;
            for (int j = 18; j >= 0; j -- ) 
                if ((pos + (1ll << j) < n) && tr[pos + (1ll << j)] <= s) 
                    pos = (pos + (1 << j)), s -= tr[pos];
            return pos;
        }
    };

    struct DSU {  
        std::vector<int> f, siz;  
        DSU(int n) : f(n), siz(n, 1) { std::iota(f.begin(), f.end(), 0); }  
    
        int leader(int x) {  
            while (x != f[x]) x = f[x] = f[f[x]];  
            return x;  
        }  
    
        bool same(int x, int y) { return leader(x) == leader(y); }  
    
        bool merge(int x, int y) {  
            x = leader(x);  
            y = leader(y);  
            if (x == y) return false;  
            siz[x] += siz[y];  
            f[y] = x;
            return true;  
        }  
        
        int size(int x) { return siz[leader(x)]; }  
    };

    signed main() {
        std::cin.tie(nullptr)->sync_with_stdio(false);

        int n; std::cin >> n;
        int now = n;
        std::vector<std::array<int, 3>> edge;
        std::vector<std::vector<int>> adj(n * 2);
        std::vector<int> val(n * 2);
        for (int i = 1; i < n; i++) {
            int u, v, w;
            std::cin >> u >> v >> w;
            edge.push_back({w, u, v});
        }

        DSU uf(n * 2 + 1);
        std::sort(edge.begin(), edge.end(), std::greater<std::array<int, 3>>());

        for (auto& [w, u, v] : edge) {
            int fu = uf.leader(u), fv = uf.leader(v);
            val[++now] = w;
            uf.f[fu] = uf.f[fv] = now;
            adj[now].push_back(fu), adj[now].push_back(fv);
        }

        Fenwick<int> bit(now);

        std::vector<int> siz(now + 1);
        std::vector<std::array<int, 2>> seg(now + 1);
        int idx = 0;

        std::function<void(int)> dfs = [&](int u) -> void {
            siz[u] = (u <= n);
            seg[u][0] = ++idx;
            for (auto& v : adj[u]) {
                dfs(v);
                siz[u] += siz[v];
            }
            seg[u][1] = idx;
        };

        dfs(now);

        auto change = [&](int x, int v) -> void {
            bit.add(seg[x][0], v);
            bit.add(seg[x][1] + 1, -v);
        };

        for (int i = n + 1; i <= now; i++) {
            change(adj[i][0], siz[adj[i][1]] * val[i]);
            change(adj[i][1], siz[adj[i][0]] * val[i]);
        }

        for (int i = 1; i <= n; i++) std::cout << bit.sum(seg[i][0]) << "\n";
        return 0 ^ 0;
    }

标签:std,int,siz,Kruskal,WC2014,权值,now,leader
From: https://www.cnblogs.com/Haven-/p/16855777.html

相关文章