bzoj2282
树的直径+单调队列
这竟然和bzoj1999是一样的?
我们yy一下,发现这条路径肯定在树的直径上,然后就好办了,我们维护一个双指针,保证长度<=s,然后最大距离就是直径的两端到路径的两端的最大值,还有当前路径上挂着的链,这个我们dfs一下就行了,然后直径两端的最大值直接求就行了,链的最大值维护一个单调队列,那么就可以O(n)出解了,求直径用两次bfs
bzoj1999卡到rank1了!
bzoj2282rank2!
#include<bits/stdc++.h> using namespace std; const int N = 500010; struct edge { int nxt, to, w; } e[N << 1]; int n, cnt = 1, S, ans = 0x3f3f3f3f; int d[N], route[N], head[N], vis[N], dis[N], dep[N], q[N], last[N]; namespace IO { const int Maxlen = N * 50; char buf[Maxlen], *C = buf; int Len; inline void read_in() { Len = fread(C, 1, Maxlen, stdin); buf[Len] = '\0'; } inline void fread(int &x) { x = 0; int f = 1; while (*C < '0' || '9' < *C) { if(*C == '-') f = -1; ++C; } while ('0' <= *C && *C <= '9') x = (x << 1) + (x << 3) + *C - '0', ++C; x *= f; } inline void read(int &x) { x = 0; int f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1) + (x << 3) + c - '0'; c = getchar(); } x *= f; } inline void read(long long &x) { x = 0; long long f = 1; char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { x = (x << 1ll) + (x << 3ll) + c - '0'; c = getchar(); } x *= f; } } using namespace IO; void link(int u, int v, int w) { e[++cnt].nxt = head[u]; head[u] = cnt; e[cnt].to = v; e[cnt].w = w; } int bfs(int s) { int ret = s, l = 1, r = 0; d[s] = 0; q[++r] = s; last[s] = 0; while(l <= r) { int u = q[l++]; for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != e[last[u] ^ 1].to) { d[e[i].to] = d[u] + e[i].w; if(d[e[i].to] > d[ret]) ret = e[i].to; q[++r] = e[i].to; last[e[i].to] = i; } } return ret; } int dfs(int u) { int ret = 0; vis[u] = 1; for(int i = head[u]; i; i = e[i].nxt) if(!vis[e[i].to]) ret = max(ret, dfs(e[i].to) + e[i].w); return ret; } int main() { read_in(); fread(n); fread(S); for(int i = 1; i < n; ++i) { int u, v, w; fread(u); fread(v); fread(w); link(u, v, w); link(v, u, w); } int s = bfs(1), t = bfs(s), now = t, p = 0, l = 1, r = 0; while(now != s) route[++route[0]] = now, vis[now] = 1, now = e[last[now] ^ 1].to; route[++route[0]] = s; vis[s] = 1; for(int i = 1; i <= route[0]; ++i) { int tmp = i == 1 ? 0 : e[last[route[i - 1]]].w; dis[i] = dis[i - 1] + tmp; dep[i] = dfs(route[i]); } for(int i = 1; i <= route[0]; ++i) { int mx = dis[i]; while(l <= r && q[l] < i) ++l; while(dis[p + 1] - dis[i] <= S && p < route[0]) { ++p; while(l <= r && dep[p] > dep[q[r]]) --r; q[++r] = p; } mx = max(mx, max(dis[route[0]] - dis[p], dep[q[l]])); ans = min(ans, mx); } printf("%d\n", ans); return 0; }