제출 #794899

#제출 시각아이디문제언어결과실행 시간메모리
794899PurpleCrayonDesignated Cities (JOI19_designated_cities)C++17
30 / 100
2094 ms40752 KiB
#include <bits/stdc++.h>
using namespace std;

#define sz(v) int(v.size())
#define ar array
typedef long long ll;
const int N = 2e5+10, MOD = 1e9+7;
const ll INF = 1e18+10;

int n;
vector<ar<int, 3>> adj[N];
ll ans[N];

ll calc_one(int c, int p) {
    ll sum = 0;
    for (auto [nxt, w, _] : adj[c]) if (nxt != p) {
        sum += w + calc_one(nxt, c);
    }
    return sum;
}

void dfs1(int c, int p, ll x) {
    ans[1] = min(ans[1], x);
    for (auto [nxt, a, b] : adj[c]) if (nxt != p) {
        dfs1(nxt, c, x - a + b);
    }
}

int sub[N];
bool blocked[N];

int dfs_sub(int c, int p) {
    sub[c] = 1;
    for (auto [nxt, x, y] : adj[c]) if (nxt != p && !blocked[nxt]) {
        sub[c] += dfs_sub(nxt, c);
    }

    return sub[c];
}

int dfs_cent(int c, int p, int cnt) {
    for (auto [nxt, x, y] : adj[c]) if (nxt != p && !blocked[nxt] && sub[nxt] > cnt / 2)
        return dfs_cent(nxt, c, cnt);

    return c;
}

pair<ll, int> dfs_best(int c, int p, ll x) {
    pair<ll, int> best{x, c};
    for (auto [nxt, w, _] : adj[c]) if (!blocked[nxt] && nxt != p) {
        best = max(best, dfs_best(nxt, c, x + w));
    }

    return best;
}

vector<int> roots;
int process(int c) {
    roots.push_back(c); // can't hurt, and probably useful

    ll best_w = -1;
    int best_nxt = -1, best_c = -1;

    for (auto [nxt, w, _] : adj[c]) if (!blocked[nxt]) {
        auto cur = dfs_best(nxt, c, w);
        if (cur.first > best_w) {
            best_w = cur.first;
            best_nxt = nxt;
            best_c = cur.second;
        }
    }

    if (best_c != -1) {
        roots.push_back(best_c);
    }
    return best_nxt;
}

void build(int c) {
    if (c == -1) return;
    int cnt = dfs_sub(c, -1);
    int cent = dfs_cent(c, -1, cnt);

    int nxt = process(cent);
    blocked[cent] = 1;
    build(nxt);
}


int par[N], par_w[N];
ll sum[N];
bool marked[N];

void dfs_root(int c, int p) {
    par[c] = p;
    for (auto [nxt, w, _] : adj[c]) if (nxt != p) {
        par_w[nxt] = w;
        sum[nxt] = sum[c] + w;
        dfs_root(nxt, c);
    }
}

void add(int root) {
    sum[root] = par_w[root] = 0;
    dfs_root(root, -1);

    auto get_cost = [&](vector<int> p) {
        memset(marked, 0, sizeof(marked));
        vector<ll> cost(n);
        for (int c : p) {
            int cur = c;
            while (cur != -1 && !marked[cur]) {
                marked[cur] = 1;
                cost[c] += par_w[cur];
                cur = par[cur];
            }
        }
        return cost;
    };

    vector<int> p(n); iota(p.begin(), p.end(), 0);
    sort(p.begin(), p.end(), [&](int x, int y) {
        return sum[x] > sum[y];
    });
    auto base_cost = get_cost(p);

    sort(p.begin(), p.end(), [&](int x, int y) {
        return base_cost[x] > base_cost[y];
    });
    auto real_cost = get_cost(p);

    ll cur = accumulate(par_w, par_w + n, 0LL);
    sort(real_cost.rbegin(), real_cost.rend());

    int cnt = 1;
    for (ll x : real_cost) {
        cur -= x;
        cnt++;

        ans[cnt] = min(ans[cnt], cur);
    }

    assert(cur == 0);
}

void solve() {
    cin >> n;
    for (int i = 0; i < n-1; i++) {
        int a, b; cin >> a >> b, --a, --b;
        int x, y; cin >> x >> y;
        adj[a].push_back({b, x, y});
        adj[b].push_back({a, y, x});
    }

    fill(ans, ans + n, INF);
    ll cost_one = calc_one(0, -1);
    dfs1(0, -1, cost_one);

    build(0);
    assert(sz(roots) <= 40);
    sort(roots.begin(), roots.end());
    roots.resize(unique(roots.begin(), roots.end()) - roots.begin());
    for (int c : roots) add(c);

    int q; cin >> q;
    while (q--) {
        int x; cin >> x;
        cout << ans[x] << '\n';
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    int T = 1;
    // cin >> T;
    while (T--) solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...