Luogu 1099 树网的核
bzoj1999 数据加强版(n <= 5e5)
较早的noip题,值得研究
重要结论:直径的最长性,任何从直径中离开直径的点到它离开的点的距离,都不会比直径的另一端到它离开的点长(否则就有新的直径出现了嘛)
在求不经过直径的最长距离的时候犯错了,要考虑的是最远的点到现在点的距离,而不是只考虑儿子,码力还是太差……
包括代码的简洁性,多开了冗余的数组,都应当思考仔细
Code:
#include <cstdio> using namespace std; const int N = 5e5 + 5; int n, s, tot = 0, head[N], fa[N], dis[N]; int pa = 1, pb = 1, maxv = 0, tmpMaxDis = 0; bool vis[N]; struct Edge { int to, nxt, val; } e[N << 1]; inline void add(int from, int to, int val) { e[++tot].to = to; e[tot].val = val; e[tot].nxt = head[from]; head[from] = tot; } inline void read(int &X) { X = 0; char ch = 0; int op = 1; for(; ch > '9' || ch < '0'; ch = getchar()) if(ch == '-') op = -1; for(; ch >= '0' && ch <= '9'; ch = getchar()) X = (X << 3) + (X << 1) + ch - 48; X *= op; } inline int max(int x, int y) { return x > y ? x : y; } inline int min(int x, int y) { return x > y ? y : x; } void dfs(int x, int fat) { fa[x] = fat; for(int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if(y == fat) continue; dis[y] = dis[x] + e[i].val; dfs(y, x); } } inline void getDia() { dfs(1, 0); for(int i = 2; i <= n; i++) if(dis[pa] < dis[i]) pa = i; dis[pa] = 0; dfs(pa, 0); for(int i = 2; i <= n; i++) if(dis[pb] < dis[i]) pb = i; for(int x = pb; x != 0; x = fa[x]) vis[x] = 1; } void dfs2(int x, int ndis) { for(int i = head[x]; i; i = e[i].nxt) { int y = e[i].to; if(y == fa[x] || vis[y]) continue; tmpMaxDis = max(tmpMaxDis, ndis + e[i].val); dfs2(y, ndis + e[i].val); } } inline void getMaxDis() { for(int i = 1; i <= n; i++) if(vis[i]) { tmpMaxDis = 0; dfs2(i, 0); maxv = max(maxv, tmpMaxDis); } } int main() { read(n), read(s); for(int x, y, v, i = 1; i < n; i++) { read(x), read(y), read(v); add(x, y, v), add(y, x, v); } getDia(); getMaxDis(); int ans = 1 << 30; /* for(int i = pb; i; i = fa[i]) maxv = max(maxv, maxDis[i]); for(int j = d.size() - 1, i = d.size() - 1; i >= 0; i--) { if(j != 0) for(; j >= 0; j--) { if(dis[d[j]] - dis[d[i]] > s) { j++; break; } } if(j == -1) j++; int tmp = max(maxv, max(dis[d[i]], dis[pb] - dis[d[j]])); ans = min(ans, tmp); } */ for(int j = pb, i = pb; i; i = fa[i]) { for(; fa[j] && dis[i] - dis[fa[j]] <= s; j = fa[j]); int tmp = max(maxv, max(dis[j], dis[pb] - dis[i])); ans = min(ans, tmp); } printf("%d\n", ans); return 0; }