社区讨论

萌新初学虚树1ms,样例过但AC on #9#10,WA on other,求条

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

讨论操作

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

当前回复
4 条
当前快照
1 份
快照标识符
@mm2uqz71
此快照首次捕获于
2026/02/26 10:36
2 周前
此快照最后确认于
2026/02/27 15:25
2 周前
查看原帖
CPP
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 250005;
int n,m,k,tot,a[2 * N],dfn[N],dp[N],dep[N],fa[N][21],mv[N][21];
bool vis[N];
vector<pair<int,int> > g[N],vt[N];
void dfs(int x,int f){
    dfn[x] = ++tot;
    fa[x][0] = f;
    dep[x] = dep[f] + 1;
    for (int i = 1; 1 << i <= dep[x]; i++){
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
        mv[x][i] = min(mv[x][i - 1],mv[fa[x][i - 1]][i - 1]);
    }
    for (int i = 0; i < g[x].size(); i++){
        int nxt = g[x][i].first,num = g[x][i].second;
        if (nxt != f){
            mv[nxt][0] = num;
            dfs(nxt,x);
        }
    }
}
int get_lca(int x,int y){
    if (dep[x] < dep[y]) swap(x,y);
    for (int i = 20; i >= 0; i--) if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
    if (x == y) return x;
    for (int i = 20; i >= 0; i--) if (fa[x][i] != fa[y][i]){
        x = fa[x][i];
        y = fa[y][i];
    }
    return fa[x][0];
}
int get_min(int x,int y){
    if (dep[x] < dep[y]) swap(x,y);
    int res = 1e18;
    for (int i = 20; i >= 0; i--) if (dep[fa[x][i]] >= dep[y]){
        res = min(res,mv[x][i]);
        x = fa[x][i];
    }
    return res;
}
bool cmp(int x,int y){return dfn[x] < dfn[y];}
void build(int len,int a[]){
    sort(a + 1,a + len + 1,cmp);
    for (int i = 2; i <= len; i++) a[len + i - 1] = get_lca(a[i - 1],a[i]);
    sort(a + 1,a + len * 2,cmp);
    len = unique(a + 1,a + len * 2) - a;
    for (int i = 1; i < len; i++) vt[a[i]].clear();
    for (int i = 2; i < len; i++){
        int f = get_lca(a[i - 1],a[i]);
        vt[f].push_back({a[i],get_min(f,a[i])});
    }
}
void DP(int x){
    dp[x] = 0;
    for (int i = 0; i < vt[x].size(); i++){
        int nxt = vt[x][i].first,num = vt[x][i].second;
        DP(nxt);
        dp[x] += (vis[nxt] ? num : min(num,dp[nxt]));
    }
}
signed main(){
    cin >> n;
    for (int i = 1,u,v,w; i < n; i++){
        cin >> u >> v >> w;
        g[u].push_back({v,w});
        g[v].push_back({u,w});
    }
    dfs(1,0);
    a[1] = 1;
    for (cin >> m; m--; ){
        cin >> k;
        for (int i = 2; i <= k + 1; i++){
            cin >> a[i];
            vis[a[i]] = 1;
        }
        build(k + 1,a);
        DP(1);
        cout << dp[1] << '\n';
        for (int i = 2; i <= k + 1; i++) vis[a[i]] = 0;
    }
    return 0;
}
没有用栈建虚树,用的 dfs 序。

回复

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

正在加载回复...