求卡常
查看原帖
求卡常
722313
Whiking楼主2024/7/26 17:23

T on #10。

用的对 dfn 排序求 lca 的建树方法,因为人傻,所以常熟很大,求卡常。

#include <bits/stdc++.h>
#define ll long long
#define F first
#define S second
const int N = 2.5e5 + 10, M = 2e5 + 10, inf = 1e9;
inline int read() {
    int x = 0, f = 1; char ch = getchar();
    for (; ch < '0' || ch > '9'; ch = getchar()) if (ch == '-') f = -1;
    for (; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
    return x * f;
}
void write( int x) {
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}
using namespace std;
int n, m;
ll dp[N];
int h[N], vis[N];
vector< pair< int, int> > G[N], Gv[N];
int fa[21][N], mi[21][N], dep[N], dfn[N];
int tot;
void dfs( int u, int fu, int w) {
    dfn[u] = ++ tot, dep[u] = dep[fu] + 1, fa[0][u] = fu, mi[0][u] = w;
    for ( int i = 1; i < 21; i ++) fa[i][u] = fa[i - 1][fa[i - 1][u]];
    for ( int i = 1; i < 21; i ++) mi[i][u] = min(mi[i - 1][u], mi[i - 1][fa[i - 1][u]]);
    for ( auto i : G[u]) if (i.F != fu) dfs(i.F, u, i.S);
}
pair< int, int> query( int u, int v) {
    int res = inf;
    if (dep[u] < dep[v]) swap(u, v);
    for ( int i = 20; i >= 0; i --)
        if (dep[fa[i][u]] >= dep[v]) res = min(res, mi[i][u]), u = fa[i][u];
    if (u == v) return {u, res};
    for ( int i = 20; i >= 0; i --) if (fa[i][u] != fa[i][v])
        res = min(res, min(mi[i][u], mi[i][v])), u = fa[i][u], v = fa[i][v];
    res = min(res, min(mi[0][u], mi[0][v]));
    return {fa[0][u], res};
}
int tr[N], len;
int cmp( int a, int b) { return dfn[a] < dfn[b]; }
void build( int k) {
    len = 0;
    for ( register int i = 1; i <= k; i ++) tr[++ len] = h[i];
    tr[++ len] = 1;
    sort(tr + 1, tr + k + 1, cmp), len = unique(tr + 1, tr + len + 1) - tr - 1;
    for ( register int i = 1; i < k; i ++) tr[++ len] = query(tr[i], tr[i + 1]).F;
    sort(tr + 1, tr + len + 1, cmp), len = unique(tr + 1, tr + len + 1) - tr - 1; 
    for ( register int i = 1; i < len; i ++) {
        auto res = query(tr[i], tr[i + 1]);
        int res2 = query(res.F, tr[i + 1]).S;
        Gv[res.F].push_back({tr[i + 1], res2});
    }
    function< void( int, int)> solve = [&]( int u, int fu) {
        dp[u] = 0;
        for ( auto i : Gv[u]) {
            int v = i.F, w = i.S;
            if (v == fu) continue ;
            solve(v, u);
            if (vis[v]) dp[u] += w; else dp[u] += min(dp[v], 1ll * w);
        }
    } ;
    solve(1, 0);
    for ( int i = 1; i <= len; i ++) Gv[tr[i]].clear();
}
signed main() {
    n = read();
    for ( int i = 1, u, v, w; i < n; i ++) {
        u = read(), v = read(), w = read();
        G[u].push_back({v, w}), G[v].push_back({u, w});
    }
    memset(mi, 127, sizeof mi);
    dep[0] = 1;
    dfs(1, 0, inf);
    m = read();
    while (m --) {
        int k = read();
        for ( int i = 1; i <= k; i ++) h[i] = read(), vis[h[i]] = 1;
        build(k);
        printf("%lld\n", dp[1]);
        for ( int i = 1; i <= k; i ++) vis[h[i]] = 0;
    }
}
2024/7/26 17:23
加载中...