BZOJ 1546: uva4409 - Ironman Race in Treeland

太菜了太菜了 点分治都不会写了
求一条路径长度不超过 \(K\),且价值最大
点分治
遍历重心的每一个子树,得到一个子树之后先将 \((dep,val)\) 进行排序,然后 \(dep\)\(val\) 必须同时增加,所以就是取 \(val\) 的前缀 max
然后得到一个子树排好序的 \((dep, val)\) 的有序表之后,就枚举之前遍历过的子树的二元组,在当前有序表上二分一个 \(val\) 最大值即可
复杂度 \(O(n \log ^ 2 n)\)
注意这种取max的题就不能容斥得到答案了
之前写过这种找max的感觉很难写
现在写起来感觉还好。

#include <bits/stdc++.h>
#define pii pair<int, int>
#define pb push_back
#define fi first
#define se second

char buf[1 << 21], *p1 = buf, *p2 = buf;
inline char getc() {
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
inline int read() {
    int x = 0, f = 1; char ch = getc();
    while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getc(); }
    while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getc(); }
    return x * f;
}
inline bool chkmax(int &a, int b) { return a < b ? a = b, 1 : 0; }
inline bool chkmin(int &a, int b) { return a > b ? a = b, 1 : 0; }

const int N = 3e4 + 7;
const int INF = 0x3f3f3f3f;
int head[N], to[N * 2], ne[N * 2], c[N * 2], w[N * 2], cnt = 1;
int n, _, K, ans, sz[N], maxsz[N], totsz, root;
bool vis[N];
std::vector<std::pii> cur, last;

void getroot(int u, int f) {
    sz[u] = 1; maxsz[u] = 0;
    for (int i = head[u]; i; i = ne[i]) {
        int v = to[i];
        if (vis[v] || v == f) continue;
        getroot(v, u);
        sz[u] += sz[v];
        chkmax(maxsz[u], sz[v]);
    }
    chkmax(maxsz[u], totsz - sz[u]);
    if (maxsz[u] < maxsz[root]) root = u;
}

inline void add(int u, int v, int cc, int ww) {
    to[++cnt] = v; ne[cnt] = head[u]; c[cnt] = cc; w[cnt] = ww; head[u] = cnt;
}

int dep[N], val[N];
void dfs(int u, int f) {
    cur.pb(std::pii(dep[u], val[u]));
    if (dep[u] <= K) chkmax(ans, val[u]);
    for (int i = head[u]; i; i = ne[i]) {
        int v = to[i];
        if (vis[v] || v == f) continue;
        dep[v] = dep[u] + c[i]; val[v] = val[u] + w[i];
        dfs(v, u);
    }
}

void done(int u) {
    last.pb(std::pii(0, 0));
    dep[u] = val[u] = 0;
    for (int i = head[u]; i; i = ne[i]) {
        int v = to[i];
        if (vis[v]) continue;
        cur.clear();
        dep[v] = c[i]; val[v] = w[i];
        dfs(v, u);
        std::sort(cur.begin(), cur.end());
        for (int j = 1; j < cur.size(); j++)
            if (cur[j].se <= cur[j - 1].se) cur[j] = cur[j - 1];
        for (int j = 0; j < last.size(); j++) {
            int pos = std::upper_bound(cur.begin(), cur.end(), std::pii(K - last[j].fi, INF)) - cur.begin() - 1;
            if (pos < 0) continue;
            chkmax(ans, cur[pos].se + last[j].se);
        }
        for (int j = 0; j < cur.size(); j++)
            last.pb(cur[j]);
    }
}

void solve(int u) {
    cur.clear(); last.clear();
    vis[u] = 1;
    done(u);
    for (int i = head[u]; i; i = ne[i]) {
        int v = to[i];
        if (vis[v]) continue;
        root = 0; totsz = sz[v];
        getroot(v, 0);
        solve(root);
    }
}

int main() {
    n = read(), _ = read(), K = read();
    assert(_ == n - 1);
    for (int i = 1; i < n; i++) {
        int u = read(), v = read(), cc = read(), ww = read();
        add(u, v, cc, ww); add(v, u, cc, ww);
    }
    maxsz[root = 0] = totsz = n;
    getroot(1, 0);
    solve(root);
    printf("%d\n", ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Mrzdtz220/p/12329613.html
今日推荐