Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #include <cassert>
- using namespace std;
- using ll = long long;
- #define all(x) (x).begin(), (x).end()
- #define sz(x) (int)(x).size()
- #define pb push_back
- #define int ll
- mt19937 rnd(chrono::steady_clock::now().time_since_epoch().count());
- template<typename T>
- void shuf(vector<T>& a) {
- for (int i = 1; i < sz(a); i++) swap(a[i], a[rnd() % (i + 1)]);
- }
- vector<ll> maxconv(const vector<ll>& a, const vector<ll>& b) {
- assert(!a.empty() && !b.empty());
- vector<ll> rs = {a[0] + b[0]};
- int ia = 1, ib = 1;
- while (ia < sz(a) || ib < sz(b)) {
- if (ia < sz(a) && (ib == sz(b) || a[ia] - a[ia - 1] > b[ib] - b[ib - 1])) {
- rs.pb(rs.back() + a[ia] - a[ia - 1]);
- ia++;
- } else {
- rs.pb(rs.back() + b[ib] - b[ib - 1]);
- ib++;
- }
- }
- return rs;
- }
- void solve() {
- int n; cin >> n;
- vector<vector<pair<int, ll>>> g(n);
- for (int i = 0; i < n - 1; i++) {
- int u, v, w; cin >> u >> v >> w;
- u--; v--;
- g[u].pb({v, w});
- g[v].pb({u, w});
- }
- vector<int> used_ct(n), sub(n), from(n, -1), ct_lvl(n);
- from[0] = 0;
- auto rs = [&](int v, int p, auto&&self) -> void {
- sub[v] = 1;
- for (auto [u, w] : g[v]) {
- if (u != p && !used_ct[u]) {
- self(u, v, self);
- sub[v] += sub[u];
- }
- }
- };
- auto fc = [&](int v, int p, int is, auto&&self) -> int {
- for (auto [u, w] : g[v]) {
- if (u != p && !used_ct[u] && sub[u] > is / 2) {
- return self(u, v, is, self);
- }
- }
- return v;
- };
- vector<vector<int>> g_ct(n);
- while (true) {
- vector<pair<int, int>> sf;
- for (int i = 0; i < n; i++) {
- if (from[i] != -1) {
- rs(i, i, rs);
- int ct = fc(i, i, sub[i], fc);
- ct_lvl[ct] = (from[i] == i ? 0 : ct_lvl[from[i]] + 1);
- if (from[i] != i) g_ct[from[i]].pb(ct);
- used_ct[ct] = 1;
- for (auto [u, w] : g[ct]) {
- if (!used_ct[u]) sf.pb({u, ct});
- }
- from[i] = -1;
- }
- }
- if (sf.empty()) break;
- for (auto u : sf) from[u.first] = u.second;
- }
- vector<int> ord(n);
- iota(all(ord), 0);
- sort(all(ord), [&](int i, int j) {
- return ct_lvl[i] < ct_lvl[j];
- });
- vector<vector<int>> lvls(n);
- vector<vector<vector<ll>>> dps(n);
- vector<int> pos(20);
- for (int ps = n - 1; ps >= 0; ps--) {
- int ct = ord[ps];
- if (g_ct[ct].empty()) {
- for (auto [u, w] : g[ct]) {
- lvls[ct].pb(ct_lvl[u]);
- for (int j = 0; j < sz(lvls[ct]) - 1; j++) assert(lvls[ct][j] != lvls[ct].back());
- }
- dps[ct].assign((1 << sz(lvls[ct])), vector<ll>(1, 0));
- for (int j = 0; j < sz(g[ct]); j++) {
- dps[ct][(1 << j)].pb(g[ct][j].second);
- }
- } else {
- for (int u : g_ct[ct]) {
- for (int vl : lvls[u]) {
- if (vl != ct_lvl[ct]) lvls[ct].pb(vl);
- }
- }
- int sind = sz(lvls[ct]);
- vector<int> ws;
- for (auto [u, w] : g[ct]) {
- if (ct_lvl[u] < ct_lvl[ct]) {
- lvls[ct].pb(ct_lvl[u]);
- ws.pb(w);
- }
- }
- for (int j = 0; j < sz(lvls[ct]); j++) {
- pos[lvls[ct][j]] = j;
- }
- dps[ct].resize((1 << sz(lvls[ct])), vector<ll>(1, 0));
- for (int mask = 0; mask < (1 << sz(lvls[ct])); mask++) {
- int cntout = 0, addd = 0;
- for (int j = sind; j < sz(lvls[ct]); j++) {
- if (((mask >> j) & 1)) {
- cntout++;
- addd += ws[j - sind];
- }
- }
- if (cntout > 1) continue;
- auto rec = [&](int l, int r, auto&&self) -> array<vector<ll>, 2> {
- if (l + 1 == r) {
- vector<ll> dp0, dp1;
- int M = 0, pps = 0;
- for (int j = 0; j < sz(lvls[g_ct[ct][l]]); j++) {
- if (lvls[g_ct[ct][l]][j] == ct_lvl[ct]) {
- pps = j; continue;
- }
- int pp = pos[lvls[g_ct[ct][l]][j]];
- M += (((mask >> pp) & 1) << j);
- }
- dp0 = dps[g_ct[ct][l]][M]; dp1 = (!cntout ? dps[g_ct[ct][l]][M + (1 << pps)] : vector<ll>(0));
- for (int j = 0; j < sz(dp0); j++) {
- if (j < sz(dp1)) {
- dp1[j] = max(dp1[j], dp0[j]);
- } else {
- dp1.pb(dp0[j]);
- }
- }
- return {dp0, dp1};
- }
- int mid = (l + r) >> 1;
- auto rsl = self(l, mid, self), rsr = self(mid, r, self);
- auto newdp0 = maxconv(rsl[0], rsr[0]);
- if (cntout) return {newdp0, {}};
- auto dp11 = maxconv(rsl[1], rsr[0]), dp12 = maxconv(rsl[0], rsr[1]);
- for (int j = 0; j < sz(dp12); j++) {
- if (j < sz(dp11)) dp11[j] = max(dp11[j], dp12[j]);
- else dp11.pb(dp12[j]);
- }
- for (int j = 0; j < sz(newdp0); j++) {
- if (j < sz(dp11)) dp11[j] = max(dp11[j], newdp0[j]);
- else dp11.pb(newdp0[j]);
- }
- return {newdp0, dp11};
- };
- auto lol = rec(0, sz(g_ct[ct]), rec);
- for (int j = 0; j < sz(lol[1]); j++) {
- if (j < sz(lol[0])) lol[0][j] = max(lol[0][j], lol[1][j]);
- else lol[0].pb(lol[1][j]);
- }
- if (!cntout) {
- dps[ct][mask] = lol[0];
- } else {
- dps[ct][mask] = {0};
- for (ll &xx : lol[0]) dps[ct][mask].pb(xx + addd);
- }
- int cm = mask;
- while (cm) {
- int bit = 31 - __builtin_clz(cm);
- for (int j = 0; j < sz(dps[ct][mask - (1 << bit)]); j++) {
- if (dps[ct][mask].size() > j) dps[ct][mask][j] = max(dps[ct][mask][j], dps[ct][mask - (1 << bit)][j]);
- else dps[ct][mask].pb(dps[ct][mask - (1 << bit)][j]);
- }
- cm -= (1 << bit);
- }
- }
- for (int u : g_ct[ct]) { dps[u].clear(); lvls[u].clear(); }
- }
- }
- for (int cnt = 1; cnt <= n - 1; cnt++) {
- if (cnt < sz(dps[ord[0]][0])) {
- cout << dps[ord[0]][0][cnt] << ' ';
- } else cout << "? ";
- }
- cout << '\n';
- }
- signed main() {
- int tt = 1;
- #ifdef LOCAL
- freopen("in.txt", "r", stdin);
- freopen("out.txt", "w", stdout);
- cin >> tt;
- #else
- ios::sync_with_stdio(false);
- cin.tie(0); cout.tie(0);
- #endif
- while (tt--) {
- solve();
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment