——來自一個失去夢想的鹹魚miaom
考慮海蜇基環樹的一般套路,在確定快餐店位置的情況下,最優解中環上必有一條邊是廢的。思考枚舉這條邊,我們需要在最快的時間求剩餘部分的直徑。當前答案就是直徑/2,證明非常簡單,就離快餐店最遠的點一定是直徑端點。這個東西可以通過雙指針單調隊列維護,達到O(n)複雜度。然後我就失去了夢想,直接線段樹水過了。
線段樹做法如下:先搞出那個環,重複一遍變成序列問題,詢問一個區間的直徑。有一種情況直徑不在環上,可以預處理。另一種情況至於環上點子樹最深的點有關,使用線段樹維護那個點的深度±在環中的位置區間合併,具體見代碼~
至於怎麼搞環,不是重點,一波dfs即可(其實拓撲排序也可以)。
#include<bits/stdc++.h>
#define N 200005
#define ll long long
using namespace std;
ll n,x,y,z,m;
ll fst[N],to[N*2],nxt[N*2],len[N],l;
ll vis[N],fa[N],flag,flag1,flag2,fl[N];
ll a[N];ll b[N],d[N],M1[N],Mx[N],dep[N],vl[N],vr[N],Ans,ly;
void link(ll x,ll y,ll z)
{
to[++l]=y;len[l]=z;nxt[l]=fst[x];fst[x]=l;
to[++l]=x;len[l]=z;nxt[l]=fst[y];fst[y]=l;
}
void dfs(ll x)
{
//cout<<x<<endl;
vis[x]=1;
for (ll i=fst[x];i;i=nxt[i])
if (to[i]!=fa[x])
{
if (vis[to[i]])
{
if (!flag)
flag=x,flag1=to[i],flag2=len[i];
}
else
{
dep[to[i]]=dep[x]+len[i];
fa[to[i]]=x;
dfs(to[i]);
//fl[x]+=fl[to[i]];
}
}
}
void Dfs(ll x)
{
Mx[x]=0;
M1[x]=0;
for (ll i=fst[x];i;i=nxt[i])
if (to[i]!=fa[x]&&fl[to[i]]==0)
{
fa[to[i]]=x;
Dfs(to[i]);
Mx[x]=max(Mx[x],max(Mx[to[i]],M1[x]+M1[to[i]]+len[i]));
M1[x]=max(M1[x],M1[to[i]]+len[i]);
}
}
struct T
{
ll l,r,a;
}nd[N*8],now;
T operator+(T a,T b)
{
return (T){max(a.l,b.l),max(a.r,b.r),max(max(a.a,b.a),a.l+b.r)};
}
void build(ll k,ll l,ll r)
{
if (l==r)
{
nd[k]=(T){vl[l],vr[l],0};
return;
}
ll mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
nd[k]=nd[k<<1]+nd[k<<1|1];
}
void qry(ll k,ll l,ll r,ll x,ll y)
{
if (x<=l&&r<=y)
{
if (now.a==-1) now=nd[k];
else now=now+nd[k];
return;
}
ll mid=l+r>>1;
if (x<=mid) qry(k<<1,l,mid,x,y);
if (y>mid) qry(k<<1|1,mid+1,r,x,y);
}
int main()
{
scanf("%lld",&n);
for (ll i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&x,&y,&z);
link(x,y,z);
}
dfs(1);
for (;flag!=flag1;flag=fa[flag])
fl[a[++m]=flag]=1,b[m]=dep[flag]-dep[fa[flag]];
fl[a[++m]=flag1]=1;b[m]=flag2;
for (ll i=1;i<=m;i++)
fa[a[i]]=0,Dfs(a[i]),ly=max(ly,Mx[a[i]]);
for (ll i=1;i<=m;i++)
a[i+m]=a[i],b[i+m]=b[i];
for (ll i=1;i<=2*m;i++)
{
d[i]=d[i-1]+b[i-1];
vl[i]=M1[a[i]]-d[i];
vr[i]=M1[a[i]]+d[i];
}
build(1,1,2*m);
Ans=100000000000000L;
for (ll i=1;i<=m;i++)
{
now=(T){0,0,-1};
qry(1,1,2*m,i,i+m-1);
Ans=min(Ans,max(now.a,ly));
}
printf("%lld.%d\n",Ans/2,Ans&1?5:0);
}