BZOJ 2286 [Sdoi2011] war of attrition (virtual tree template title)

The meaning of problems

There \ (n-\) points form a tree, the right side value. \ (m \) times query, each query, given \ (K \) critical points, these keys are asked to (1 \) \ weights disconnected node number (not communicating) the minimum broken edge with. Ensure \ (1 \) number of nodes is not critical point.
\ (n, m \ le 250000 , \ sum k \ le500000 \)

answer

Consider asking how to do it only once.

Direct tree \ (dp \) on the line. With \ (dp [u] \) represents the \ (U \) minimum cost tree disconnected subtrees. For critical points must be off the \ (u \) to the father's side. Otherwise, either the minimum current point right off the top to the root of the path, either side of the break in the sub-tree (at a cost: the son of the key points in the sub-tree \ (dp \) the sum).

We can \ (1 \) number to the right side of his father's root is set to \ (+ \ infty \) , so \ (dp [1] \) is the answer.

Then consider multiple sets of data, found that \ (\ SUM k \ Le 500000 \) , obviously every time we need \ (O (k) / O (k \ log k) \) algorithm.

Then only need to build a virtual tree \ (the DP \) on the bin, each \ (O (K \ K + log K) \) . This question is also a nature, is the key point of the key ideas in the virtual tree tree can be ignored. There is no need to build out the time to build a virtual tree.

CODE

#include <cstdio>
#include <vector>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
inline void read(int &x) {
    int flg = 1; char ch; while(!isdigit(ch=getchar())) if(ch=='-')flg=-flg;
    for(x = ch-'0'; isdigit(ch=getchar()); x = x*10+ch-'0'); x *= flg;
}
typedef long long LL;
#define il inline
const int MAXN = 250005;

int n, q, m;
int fir[MAXN], to[MAXN<<1], nxt[MAXN<<1], wt[MAXN<<1], cnt; LL val[MAXN];
il void link(int u, int v, int w) {
    to[++cnt] = v; nxt[cnt] = fir[u]; fir[u] = cnt; wt[cnt] = w;
    to[++cnt] = u; nxt[cnt] = fir[v]; fir[v] = cnt; wt[cnt] = w;
}

int sz[MAXN], fa[MAXN], top[MAXN], dep[MAXN], son[MAXN], dfn[MAXN], tmr;
void dfs1(int u, int ff) {
    dep[u] = dep[fa[u] = ff] + (sz[u] = 1);
    for(int i = fir[u], v; i; i = nxt[i])
        if((v=to[i]) != ff) {
            val[v] = min(1ll*wt[i], val[u]);
            dfs1(v, u); sz[u] += sz[v];
            if(sz[v] > sz[son[u]]) son[u] = v;
        }
}

void dfs2(int u, int tp) {
    top[u] = tp; dfn[u] = ++tmr;
    if(son[u]) dfs2(son[u], tp);
    for(int i = fir[u], v; i; i = nxt[i])
        if((v=to[i]) != fa[u] && v != son[u])
            dfs2(v, v);
}
il int Lca(int u, int v) {
    while(top[u] != top[v]) {
        if(dep[top[u]] > dep[top[v]]) u = fa[top[u]];
        else v = fa[top[v]];
    }
    return dep[u] > dep[v] ? v : u;
}
int c[MAXN], stk[MAXN], indx;
vector<int>e[MAXN];
il bool cmp(int i, int j) { return dfn[i] < dfn[j]; }
il void ins(int x) {
    if(indx == 1) { stk[++indx] = x; return; }
    int lca = Lca(x, stk[indx]);
    if(lca == stk[indx]) return; //此题性质
    while(indx > 1 && dfn[stk[indx-1]] >= dfn[lca])
        e[stk[indx-1]].push_back(stk[indx]), --indx;
    if(lca != stk[indx]) e[lca].push_back(stk[indx]), stk[indx] = lca;
    stk[++indx] = x;
}
LL dp(int u) {
    if(!e[u].size()) return val[u];
    LL re = 0;
    for(int i = e[u].size()-1; i >= 0; --i)
        re += dp(e[u][i]);
    e[u].clear();
    return min(re, val[u]);
}
int main () {
    read(n);
    for(int i = 1, x, y, z; i < n; ++i)
        read(x), read(y), read(z), link(x, y, z);
    val[1] = 1ll<<60; dfs1(1, 0); dfs2(1, 1);
    read(q);
    while(q--) {
        read(m);
        for(int i = 1; i <= m; ++i) read(c[i]);
        sort(c + 1, c + m + 1, cmp);
        stk[indx=1] = 1; //1号点必须放进来
        for(int i = 1; i <= m; ++i) ins(c[i]);
        while(indx > 1) e[stk[indx-1]].push_back(stk[indx]), --indx;
        printf("%lld\n", dp(1));
    }
}

Guess you like

Origin www.cnblogs.com/Orz-IE/p/12149366.html