社区讨论

萌新求助虚树dp WA on#4 8 10

P2495【模板】虚树 / [SDOI2011] 消耗战参与者 4已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@lo887ovi
此快照首次捕获于
2023/10/27 14:22
2 年前
此快照最后确认于
2023/10/27 14:22
2 年前
查看原帖
CPP
#include<bits/stdc++.h>
#define cjb 1145141919810843
#define MAXN 250005 
#define ll long long
#define V vshojo
using namespace std;
int n, m;
int a[MAXN];
int vis[MAXN];
struct F_star
{
    int cnte = 0, head[MAXN];
    struct edge
    {
        int to, nxt;
        int dis;
    }e[MAXN << 1];
    void adde(int u, int v, int w)
    {
        e[++cnte].to = v;
        e[cnte].dis = w;
        e[cnte].nxt = head[u];
        head[u] = cnte;
    }
}E, vshojo;

ll c[MAXN];
int tcp[MAXN], fa[MAXN], dep[MAXN];
int siz[MAXN], son[MAXN], dfn[MAXN], T;
void dfs1(int u, int f)
{
    dfn[u] = ++T;
    fa[u] = f; dep[u] = dep[f] + 1; siz[u] = 1;
    for(int i = E.head[u]; i; i = E.e[i].nxt)
    {
        int v = E.e[i].to; if(v == f) continue;
        c[v] = min(c[u], 1LL*E.e[i].dis);
        dfs1(v, u);
        siz[u] += siz[v];
        if(siz[v] > siz[son[u]]) son[u] = v;
    }
}
void dfs2(int u, int tup)
{
    tcp[u] = tup;
    if(son[u]) dfs2(son[u], tup);
    for(int i = E.head[u]; i; i = E.e[i].nxt)
    {
        int v = E.e[i].to;
        if(v == fa[u] || v == son[u]) continue;
        dfs2(v, v);
    }
}
int LCA(int u, int v)
{
    while(tcp[u] != tcp[v])
    {
        if(dep[tcp[u]] >= dep[tcp[v]]) u = fa[tcp[u]];
        else v =  fa[tcp[v]];
    } 
    return dep[u] < dep[v] ? u : v;
}
bool cmp(int a, int b)
{
    return dfn[a] < dfn[b];
}

ll dp(int u)
{
    if(vis[u])
    {
        vis[u] = 0;
        return c[u];
    }
    ll ans = 0;
    for(int i = V.head[u]; i; i = V.e[i].nxt)
    {
        ans += dp(V.e[i].to);
    }
    return min(c[u], ans);
}

int sta[MAXN], top;
int main()
{
    scanf("%d", &n);
    for(int i = 1; i < n; i++)
    {
        int u, v;
        ll  w;
        scanf("%d%d%lld",&u, &v, &w);
        E.adde(u, v, w); E.adde(v, u, w);
    }
    c[1] = cjb;
    dfs1(1, 0); dfs2(1, 1);
    

    scanf("%d",&m);
    while(m--)
    {
        int k;
        scanf("%d",&k);
        for(int i = 1; i <= k; i++)
        {
            scanf("%d",&a[i]);
            vis[a[i]] = 1;
        }
        sort(a + 1, a + 1 + k, cmp);
        top = 0; V.cnte = 0;
        int dad = a[1];
        for(int i = 1; i <= k; i++)
        {
            int lc = LCA(a[i], sta[top]);
            if(lc != sta[top])
            {
                while(dfn[lc] < dfn[sta[top-1]])
                {
                    int u = sta[top - 1], v = sta[top];
                    if(dfn[u] < dfn[dad]) dad = u;
                    V.adde(u, v, 0);
                    top--;
                }
                if(dfn[lc] > dfn[sta[top-1]])
                {
                    V.head[lc] = 0;
                    V.adde(lc, sta[top], 0);
                    if(dfn[lc] < dfn[dad]) dad = lc;
                    sta[top] = lc;
                }
                else
                {
                    int u = sta[top - 1], v = sta[top];
                    if(dfn[u] < dfn[dad]) dad = u;
                    V.adde(u, v, 0);
                    top--;
                }
            }
            V.head[a[i]] = 0;
            sta[++top] = a[i];
        }
        while(top > 1)
        {
            int u = sta[top-1], v = sta[top];
            if(dfn[u] < dfn[dad]) dad = u;
            V.adde(u, v, 0); top--;
        }
        printf("%lld\n", dp(dad));
    }

    return 0;
}

回复

5 条回复,欢迎继续交流。

正在加载回复...