分析
首先两遍bfs求出树的直径,预处理对于每个点的最大偏心距,枚举直径上的左端点
l
l
l,那么对于右端点
r
r
r,答案就是
m
a
x
(
m
a
x
(
m
x
i
i
∈
[
l
∼
r
]
)
,
m
a
x
(
d
i
s
[
r
]
−
d
i
s
[
s
]
,
d
i
s
[
t
]
−
d
i
s
[
l
]
)
)
max(max(mx_i i\in[l\sim r]),max(dis[r]-dis[s],dis[t]-dis[l]))
max(max(mxii∈[l∼r]),max(dis[r]−dis[s],dis[t]−dis[l])),时间复杂度
O
(
n
3
)
O(n^3)
O(n3)
不对啊,bzoj怎么过,
首先,
r
r
r应该递增会让答案更优,所以说用双指针,so
O
(
n
2
)
O(n^2)
O(n2)
不对呀,貌似还是TLE
要用单调队列维护最大偏心距
O
(
n
)
O(n)
O(n)
代码
#include <cstdio>
#include <cstring>
#include <cctype>
#include <queue>
#define rr register
using namespace std;
struct node{int y,w,next;}e[1000001]; bool v[500001]; int n,m,k=1,s,t;
int ans=2147483647,dis[500001],pre[500001],ls[500001],mx[500001],q[500001];
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline signed bfs(int s){
rr queue<int>q; q.push(s); pre[s]=0;
memset(dis,0,sizeof(dis));
while (q.size()){
rr int x=q.front(); q.pop();
for (rr int i=ls[x];i;i=e[i].next)
if (!dis[e[i].y]&&e[i].y!=s){
dis[e[i].y]=dis[x]+e[i].w;
q.push(e[i].y); pre[e[i].y]=x;
}
}
rr int t=1;
for (rr int i=1;i<=n;++i)
t=dis[i]>dis[t]?i:t;
return t;
}
inline void bfs2(int s){
rr queue<pair<int,int> >q; q.push(make_pair(s,0));
while (q.size()){
rr int x=q.front().first,now=q.front().second; q.pop();
for (rr int i=ls[x];i;i=e[i].next)
if (!v[e[i].y]){
v[e[i].y]=1; rr int t=now+e[i].w;
mx[s]=mx[s]>t?mx[s]:t; q.push(make_pair(e[i].y,t));
}
}
}
signed main(){
n=iut(); m=iut();
for (rr int i=1;i<n;++i){
rr int x=iut(),y=iut(),w=iut();
e[++k]=(node){y,w,ls[x]}; ls[x]=k;
e[++k]=(node){x,w,ls[y]}; ls[y]=k;
}
s=bfs(1); t=bfs(s);
for (rr int i=t;i;i=pre[i]) v[i]=1;
for (rr int i=t;i;i=pre[i]) bfs2(i);
rr int r=t,head=1,tail=1; q[1]=t;
for (rr int 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;
rr int now=dis[t]-dis[l]<mx[q[head]]?mx[q[head]]:dis[t]-dis[l];
rr int tt=dis[r]-dis[s]<now?now:dis[r]-dis[s]; ans=ans<tt?ans:tt;
}
if (q[head]==l) ++head;
}
return !printf("%d",ans);
}