bzoj 2282: [Sdoi2011]消防

时间:2023-03-09 21:52:37
bzoj 2282: [Sdoi2011]消防
 #include<cstdio>
#include<cstring>
#include<iostream>
#define N 600000
using namespace std;
int cnt,n,s,head[N],next[N*],u[N*],v[N*],q[N],h,t,d[N],f[N],mx,rt1,mx1,from[N],zhan[N],tot,mark[N];
int l,r,ans;
void jia(int a1,int a2,int a3)
{
cnt++;
next[cnt]=head[a1];
head[a1]=cnt;
u[cnt]=a2;
v[cnt]=a3;
return;
}
bool pan(int a1)
{
int L=,R=tot;
for(;zhan[]-zhan[L]<=a1;L++);
for(;zhan[R]-zhan[tot]<=a1;R--);
if(zhan[L-]-zhan[R+]>s)
return ;
return ;
}
void dfs(int a1)
{
h=;
t=;
q[t]=a1;
memset(f,,sizeof(f));
f[a1]=;
d[a1]=;
for(;h<t;)
{
h++;
int p=q[h];
for(int i=head[p];i;i=next[i])
if(!f[u[i]])
{
if(mark[u[i]])
d[u[i]]=d[p];
else
d[u[i]]=d[p]+v[i];
q[++t]=u[i];
from[u[i]]=p;
f[u[i]]=;
}
}
return;
}
int main()
{
scanf("%d%d",&n,&s);
for(int i=;i<n;i++)
{
int a1,a2,a3;
scanf("%d%d%d",&a1,&a2,&a3);
jia(a1,a2,a3);
jia(a2,a1,a3);
}
dfs();
mx=;
for(int i=;i<=n;i++)
if(mx<d[i])
{
mx=d[i];
rt1=i;
}
dfs(rt1);
mx=;
for(int i=;i<=n;i++)
if(mx<d[i])
{
mx=d[i];
mx1=i;
}
r=d[mx1];
zhan[++tot]=d[mx1];
mark[mx1]=;
for(;mx1!=rt1;)
{
mx1=from[mx1];
zhan[++tot]=d[mx1];
mark[mx1]=;
}
dfs(rt1);
for(int i=;i<=n;i++)
if(d[i]>l)
l=d[i];
for(;l<=r;)
{
int mid=(l+r)>>;
if(pan(mid))
{
ans=mid;
r=mid-;
}
else
l=mid+;
}
printf("%d\n",ans);
return ;
}

显然最长距离最短,一定是在直径上,我们先DFS两遍找出直径,把直径上的边赋值成0,跑一遍dfs,找一个最大值作为l,二分答案判断。