[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1999
[算法]
树的直径 + 单调队列
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 500010 const int INF = 2e9; int i,n,s,ans,head,tail,m,t,tot,u,v,w,l,r; int pre[MAXN],dis[MAXN],h[MAXN],f[MAXN],mx[MAXN],q[MAXN]; bool visited[MAXN]; struct edge { int to,w,nxt; } e[MAXN << 1]; vector< pair<int,int> > path; inline void addedge(int u,int v,int w) { tot++; e[tot] = (edge){v,w,h[u]}; h[u] = tot; } inline int bfs(int s) { int i,cur,v,w,m; queue< int > q; q.push(s); dis[s] = 0; pre[s] = 0; while (!q.empty()) { cur = q.front(); q.pop(); for (i = h[cur]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!dis[v] && v != s) { dis[v] = dis[cur] + w; q.push(v); pre[v] = cur; } } } m = 1; for (i = 2; i <= n; i++) { if (dis[i] > dis[m]) m = i; } return m; } inline void bfsII(int s) { int i,cur,v,w; queue< int > q; q.push(s); while (!q.empty()) { cur = q.front(); q.pop(); for (i = h[cur]; i; i = e[i].nxt) { v = e[i].to; w = e[i].w; if (!visited[v] && !f[v]) { visited[v] = true; f[v] = f[cur] + w; mx[s] = max(mx[s],f[v]); q.push(v); } } } } int main() { scanf("%d%d",&n,&m); for (i = 1; i < n; i++) { scanf("%d%d%d",&u,&v,&w); addedge(u,v,w); addedge(v,u,w); } s = bfs(1); memset(dis,0,sizeof(dis)); t = bfs(s); for (i = t; i; i = pre[i]) visited[i] = true; for (i = t; i; i = pre[i]) bfsII(i); q[1] = t; l = r = t; head = tail = 1; ans = INF; for (l = t; l; l = pre[l]) { while (pre[r] && dis[l] - dis[pre[r]] <= m) { r = pre[r]; while (head <= tail && mx[q[tail]] <= mx[r]) tail--; q[++tail] = r; ans = min(ans,max(mx[q[head]],max(dis[r] - dis[s],dis[t] - dis[l]))); } if (q[head] == l) head++; } printf("%d ",ans); return 0; }