# bzoj3784 树上的路径

【题解】

upd:距离最多nlogn个。

# include <queue>
# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10, N = 1e6 + 10;
const int mod = 1e9+7;

# define RG register

int n, m;
int head[M], nxt[M], to[M], tot=0, w[M];
inline void add(int u, int v, int _w) {
++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; w[tot] = _w;
}
inline void adde(int u, int v, int _w) {
add(u, v, _w), add(v, u, _w);
}

int val[N], L[N], R[N], tn = 0;

namespace DFZ {
bool vis[M];
int sz[M], mx[M];
inline void getsize(int x, int fa=0) {
sz[x] = 1, mx[x] = 0;
for (int i=head[x]; i; i=nxt[i]) {
if(to[i] == fa || vis[to[i]]) continue;
getsize(to[i], x);
sz[x] += sz[to[i]];
if(sz[to[i]] > mx[x]) mx[x] = sz[to[i]];
}
}
int mi, centre;
inline void getcentre(int x, int tp, int fa=0) {
if(sz[tp] - sz[x] > mx[x]) mx[x] = sz[tp] - sz[x];
if(mx[x] < mi) mi = mx[x], centre = x;
for (int i=head[x]; i; i=nxt[i]) {
if(to[i] == fa || vis[to[i]]) continue;
getcentre(to[i], tp, x);
}
}
int curl, curr;

inline void calc(int x, int fa, int dis) {
val[++tn] = dis, L[tn] = curl, R[tn] = curr;
for (int i=head[x]; i; i=nxt[i])
if(to[i] != fa && !vis[to[i]]) calc(to[i], x, dis+w[i]);
}

inline void dfs(int x) {
getsize(x); mi=n; getcentre(x, x);
x = centre;

++tn;
curl = curr = tn;

for (int i=head[x]; i; i=nxt[i])
if(!vis[to[i]]) calc(to[i], x, w[i]), curr = tn;

vis[x] = 1;
for (int i=head[x]; i; i=nxt[i])
if(!vis[to[i]]) dfs(to[i]);
}
}

namespace ST {
struct rmq {
int i, v;
rmq() {}
rmq(int i, int v) : i(i), v(v) {}
friend bool operator <(rmq a, rmq b) {
return a.v<b.v;
}
friend bool operator >(rmq a, rmq b) {
return a.v>b.v;
}
};
int n, Log2[N];
rmq f[N][21];
inline void init(int _n) {
n = _n;
Log2[1] = 0;
for (int i=2; i<=n; ++i) Log2[i] = Log2[i>>1] + 1;
for (int i=1; i<=n; ++i) f[i][0] = rmq(i, val[i]);
for (int j=1; j<=20; ++j)
for (int i=1; i+(1<<j)-1<=n; ++i)
f[i][j] = max(f[i][j-1], f[i+(1<<(j-1))][j-1]);
}
inline bool getpos(int l, int r, int &i, int &v) {
if(l > r) return 0;
int len = Log2[r-l+1];
rmq t = max(f[l][len], f[r-(1<<len)+1][len]);
i = t.i, v = t.v;
return 1;
}
}

struct pa {
int x, l, r, mx, v;
pa() {}
pa(int x, int l, int r, int mx, int v) : x(x), l(l), r(r), mx(mx), v(v) {}
friend bool operator < (pa a, pa b) {
return a.v<b.v;
}
};

priority_queue<pa> q;

int main() {
scanf("%d%d", &n, &m);
for (int i=1, u, v, _w; i<n; ++i) {
scanf("%d%d%d", &u, &v, &_w);
adde(u, v, _w);
}
DFZ::dfs(1);
ST::init(tn);
while(!q.empty()) q.pop();
for (int i=1; i<=tn; ++i) {
int va, po;
ST::getpos(L[i], R[i], po, va);
q.push(pa(i, L[i], R[i], po, va+val[i]));
}
for (int i=1; i<=m; ++i) {
pa t = q.top();
printf("%d\n", t.v);
q.pop();
int va, po;
if(ST::getpos(t.l, t.mx-1, po, va))
q.push(pa(t.x, t.l, t.mx-1, po, val[t.x]+va));
if(ST::getpos(t.mx+1, t.r, po, va))
q.push(pa(t.x, t.mx+1, t.r, po, val[t.x]+va));
}
return 0;
}
View Code

posted @ 2017-05-01 20:09  Galaxies  阅读(274)  评论(0编辑  收藏  举报