1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| #include <bits/stdc++.h> #define pb push_back #define fi first #define se second using DB = double; const int N = 1e5 + 100; const DB eps = 1e-4; int n, numl, numr; bool del[N << 2]; DB res, lp[N << 1], rp[N << 1], l = 0, r = 1e6, mid, ans; std::vector< std::pair<int, int> > G[N << 1]; int h[N << 1], idx = 0, mxs, si[N << 1], rte, cl, cr, hh, tt; struct Edge{ int ne, ver, w; } e[N << 2]; std::pair<DB, int> q[N << 1]; void add(int x, int y, int z){ e[idx] = {h[x], y, z}, h[x] = idx++; } void dfs(int x, int fa) { for (int i = h[x]; ~i; i = e[i].ne) if (e[i].ver != fa) { dfs(e[i].ver, x); G[x].pb({e[i].ver, e[i].w}); } } void rebuild() { dfs(1, -1); std::memset(h, -1, sizeof h), idx = 0; for (int i = 1, lc, rc; i <= n; ++i) if (G[i].size() <= 2) for (auto t : G[i]) add(i, t.fi, t.se), add(t.fi, i, t.se); else { lc = ++n, rc = ++n; add(i, lc, 0), add(lc, i, 0); add(i, rc, 0), add(rc, i, 0); for (auto t : G[i]) G[lc].pb(t), std::swap(lc, rc); } } void get_rt(int x, int fa, int tot) { si[x] = 1; for (int i = h[x], y, mx; ~i; i = e[i].ne) if (!del[i] && (y = e[i].ver) != fa) { get_rt(y, x, tot); si[x] += si[y], mx = std::max(si[y], tot - si[y]); if (mx < mxs) mxs = mx, rte = i; } } void walk(int x, int fa, int len, DB w, DB *p, int &cp, bool is) { if (is) { if (cp < len) p[cp = len] = w; else p[len] = std::max(w, p[len]); } si[x] = 1; for (int i = h[x], y; ~i; i = e[i].ne) if (!del[i] && (y = e[i].ver) != fa) { walk(y, x, len + (e[i].w != 0), w + e[i].w - mid * (e[i].w != 0), p, cp, is | (e[i].w != 0)); si[x] += si[y]; } } void calc(int x, int tot) { mxs = n, rte = -1; get_rt(x, -1, tot); if (rte ==-1 || del[rte]) return ; x = rte; del[x] = del[x ^ 1] = true; int lc = e[x].ver, rc = e[x ^ 1].ver; walk(lc, rc, 0, 0, lp, cl = 0, 1); walk(rc, lc, e[x].w != 0, e[x].w - mid * (e[x].w != 0), rp, cr = 0, e[x].w != 0); hh = 1, tt = 0; for (int i = 0, j = cl; i <= cr; ++i) { while (j >= 0 && i + j >= numl) { while (hh <= tt && q[tt].fi < lp[j]) --tt; q[++tt] = {lp[j], j}; --j; } while (hh <= tt && i + q[hh].se > numr) ++hh; if (hh <= tt) res = std::max(res, rp[i] + q[hh].fi); } calc(lc, si[lc]), calc(rc, si[rc]); } bool chk() { for (int i = 0; i < idx; ++i) del[i] = false; res = -1e9; calc(1, n); return res >= 0; } int main() { std::memset(h, -1, sizeof h), idx = 0; scanf("%d %d %d", &n, &numl, &numr); for (int i = 1, x, y, z; i < n; ++i) scanf("%d %d %d", &x, &y, &z), add(x, y, z), add(y, x, z); rebuild(); while (r - l > eps) { mid = (l + r) / 2; if (chk()) ans = l = mid; else r = mid; } printf("%.3lf\n", ans); return 0; }
|