• 虚树


    • 如果关键节点比较少,可以用虚树,把非关键节点的链化成边或删去

    • 例题 : luogu P2495 [SDOI2011]消耗战

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    typedef long long ll;
    const int N = 2.5e5 + 5;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar())
            if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar())
            x = x * 10 + c - '0';
        return x * f;
    }
    
    struct Edge {
        int n, t, d;
    }e[N*2];
    int h[N], edc;
    
    void Add(int x, int y, int z = 0) {
        e[++edc] = (Edge) {h[x], y, z}; h[x] = edc;
    }
    
    int n, fa[N], dep[N], son[N], sz[N], tp[N], dfn[N], dfc, a[N], stk[N], top;
    bool v[N];
    ll d[N];
    
    void Dfs(int x) {
        sz[x] = 1; dep[x] = dep[fa[x]] + 1;
        for (int i = h[x], y; i; i = e[i].n) {
            if ((y = e[i].t) == fa[x]) continue;
            d[y] = std::min(d[x], (ll)e[i].d);
            fa[y] = x; Dfs(y); sz[x] += sz[y];
            if (!son[x] || sz[son[x]] < sz[y]) son[x] = y;
        }
    }
    
    void Dfs(int x, int top) {
        tp[x] = top; dfn[x] = ++dfc;
        if (son[x]) Dfs(son[x], top);
        for (int i = h[x], y; i; i = e[i].n)
            if ((y = e[i].t) != fa[x] && y != son[x]) Dfs(y, y);
    }
    
    bool Cmp(const int &a, const int &b) {
        return dfn[a] < dfn[b];
    }
    
    int Lca(int x, int y) {
        while (tp[x] != tp[y])
            dep[tp[x]] > dep[tp[y]] ? x = fa[tp[x]] : y = fa[tp[y]];
        return dep[x] < dep[y] ? x : y;
    }
    
    ll Cal(int x) {
        ll ans = 0;
        for (int i = h[x], y; i; i = e[i].n)
            ans += Cal(e[i].t);
        if (v[x]) ans = d[x];
        else ans = std::min(d[x], ans);
        v[x] = h[x] = 0;
        return ans;
    }
    
    int main() {
        n = read();
        for (int i = 1; i < n; ++i) {
            int x = read(), y = read(), z = read();
            Add(x, y, z); Add(y, x, z);
        }
        d[1] = 1e18; Dfs(1); Dfs(1, 1);
        memset(h + 1, 0, n * 4); edc = 0;
        for (int m = read(); m; --m) {
            int k = read();
            for (int i = 1; i <= k; ++i) a[i] = read();
            std::sort(a + 1, a + k + 1, Cmp);
            stk[top = 1] = 1;
            for (int i = 1; i <= k; ++i) {
                int lca = Lca(stk[top], a[i]); v[a[i]] = 1;
                if (lca == stk[top]) { stk[++top] = a[i]; continue; }
                for (; top > 1 && dep[stk[top]] > dep[lca]; --top) 
                    Add(dep[stk[top-1]] > dep[lca] ? stk[top-1] : lca, stk[top]);
                if (dep[lca] > dep[stk[top]]) stk[++top] = lca;
                stk[++top] = a[i];
            }
            while (top > 1) Add(stk[top-1], stk[top]), top--;
            printf("%lld
    ", Cal(1)); edc = 0;
        }
        return 0;
    }
    
  • 相关阅读:
    一个回车键黑掉一台服务器——使用Docker时不要这么懒啊喂
    docker machine介绍和使用
    Docker Engine和Docker Machine介绍
    Nginx服务器之负载均衡策略
    从linux启动到rootfs的挂载分析
    Docker容器的生命周期管理
    docker的使用
    automake,autoconf使用详解
    go语言中文网中的资源
    Go工具和调试详解
  • 原文地址:https://www.cnblogs.com/shawk/p/14267268.html
Copyright © 2020-2023  润新知