总的来说,还是很容易想的,就是有点恶心。
首先,很明显只有一个环。
我们先找出这个环,给各棵树编号id[i],然后各棵树分别以环上的点为根,求出每个点的深度dep[i],根节点st[i],最深的孩子的深度furthestson[i]和不进入子树最远的点距离f[i],这些都比较好求。
我们分2种情况讨论:
(1)快餐店在环上
将环上的点以furthestson[i]为权值,等价于快餐店到点的最短距离再加上点的权值的最大值最小。
其实我们可以将这个环看成一个正圆,过快餐店的一条直径将这个圆分成2部分,快餐店顺时针到左边的点,逆时针到右边的点,我们分别将左边的点和右边的点分别放在2个单调队列中。
当我们逆时针旋转这条直径的时候,左右两边是单调的,可以用单调队列,然后更新答案即可。
(2)快餐店在树上
我们在(1)中顺便记录一下第i棵树不进入本树可以到达的最远距离h[i]
我们枚举树边(u,v),不失一般性,dep[u]<dep[v],且其长度为l。
那么这条路径v那一端最远可以到的距离为furthestson[v],u那一端最远可以到的距离为max(f[v]-l,dep[u]+h[id[st[u]]])。
然后更新答案即可。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline void clear(vector<int> *A,int a,int b){int i,j;A->clear();re(i,,a)re(j,,b)A[i].push_back();} inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=; int N;
int now,first[maxN+];
struct Tedge{int u,v,next,dis;}edge[*maxN+];
DB ans; inline void addedge(int u,int v,int dis)
{
now++;
edge[now].u=u;
edge[now].v=v;
edge[now].dis=dis;
edge[now].next=first[u];
first[u]=now;
} #define next(i) (i%cnt+1)
#define qian(i) ((i-2+cnt)%cnt+1)
int cnt,root[maxN+];
LL lon[maxN+];
int id[maxN+]; int vis[maxN+];
int fa[maxN+];
int sta[maxN+],last[maxN+],top;
inline void DFS()
{
mmst(vis,);
mmst(fa,);
vis[sta[top=]=]=;
last[]=first[];
while(top>=)
{
int u=sta[top],i=last[top],v;
for(v=edge[i].v;i!=-;i=edge[i].next,v=edge[i].v)
{
if(!vis[v])
{
last[top]=edge[i].next;
vis[sta[++top]=v]=;
last[top]=first[v];
fa[v]=u;
break;
}
if(vis[v] && v!=fa[u])
{
while(sta[top]!=v)root[++cnt]=sta[top--];
root[++cnt]=v;
return;
}
}
if(i==-)top--;
}
} inline void findround()
{
int i,j;
DFS();
re(i,,cnt)
{
id[root[i]]=i;
int v,dis;
for(j=first[root[i]],v=edge[j].v,dis=edge[j].dis;j!=-;j=edge[j].next,v=edge[j].v,dis=edge[j].dis)
if(v==root[next(i)]){lon[i]=LL(dis);break;}
}
} int head,tail,que[maxN+]; LL dep[maxN+],furthestson[maxN+],f[maxN+];
int st[maxN+];
inline void solve1(int rt)
{
int i,j;
vis[que[head=tail=]=rt]=;
dep[rt]=;
fa[rt]=;
while(head<=tail)
{
int u=que[head++],v,dis;
for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)
if(id[v]== && !vis[v])
{
fa[v]=u;
vis[que[++tail]=v]=;
dep[v]=dep[u]+LL(dis);
}
}
red(j,tail,)
{
int u=que[j],v,dis;
furthestson[u]=;
for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)
if(id[v]== && v!=fa[u])
upmax(furthestson[u],furthestson[v]+LL(dis));
}
f[rt]=;
re(j,,tail)
{
int u=que[j],v,dis;LL maxv1=,maxv2=;int hea=-;
for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)
if(id[v]== && v!=fa[u])
{
if(furthestson[v]+LL(dis)>maxv1)
maxv2=maxv1,maxv1=furthestson[v]+LL(dis),hea=v;
else
if(furthestson[v]+LL(dis)>maxv2)
maxv2=furthestson[v]+LL(dis);
}
for(i=first[u],v=edge[i].v,dis=edge[i].dis;i!=-;i=edge[i].next,v=edge[i].v,dis=edge[i].dis)
if(id[v]== && v!=fa[u])
{
if(v!=hea)
f[v]=LL(dis)+max(f[u],maxv1);
else
f[v]=LL(dis)+max(f[u],maxv2);
}
}
re(i,,tail)st[que[i]]=rt;
} DB h[maxN+]; struct Tque
{
int head,tail;
DB add,que[*maxN+],idx[*maxN+];////////////////注意,要2倍空间!!!!!!!!!!!!!!!!!!!!
inline void clear(){head=;tail=;add=0.0;}
inline void insert(int id,DB v)
{
++tail;que[tail]=v-add;idx[tail]=id;
while(tail-head+>= && que[tail]>que[tail-])que[tail-]=que[tail],idx[tail-]=idx[tail],tail--;
}
inline void erase(int id){if(idx[head]==id)head++;}
inline DB maxv(){return tail-head+>=?que[head]+add:0.0;}
}Q1,Q2; DB cir,pos[maxN+]; inline DB dist(DB p1,DB p2){return p2>=p1 ? p2-p1 : cir+p2-p1; } inline void move(DB &w,DB l){w+=l;if(w>=cir) w-=cir;} inline void solve2()
{
int i,p1,p2;
DB w1,w2;
cir=0.0;re(i,,cnt)pos[i]=cir,cir+=DB(lon[i]);
p1=;
for(p2=;pos[p2]<=cir/2.0 && p2!=cnt;p2=next(p2));
if(p2==cnt && pos[p2]<=cir/2.0)p2=next(p2);
Q1.clear();Q2.clear();
re(i,p1,qian(p2))Q1.insert(i,DB(furthestson[root[i]])+pos[i]);
if(p2!=p1) re(i,p2,qian(p1))Q2.insert(i,DB(furthestson[root[i]])+cir-pos[i]);
w1=0.0;w2=cir/2.0; mmst(vis,);
vis[]=;
while(vis[]<)
if(dist(w2,pos[p2])<=dist(w1,pos[p1]))
{
DB l=dist(w2,pos[p2]);
Q1.add-=l;
DB v1=Q1.maxv(),v2=Q2.maxv();
upmin(ans,max(v1,v2+l));
upmin(ans,max(v2,v1+l));
if(v1<=(v1+l+v2)/2.0 && (v1+l+v2)/2.0<=v1+l) upmin(ans,(v1+l+v2)/2.0);
Q2.erase(p2);
Q2.add+=l;
move(w1,l);
move(w2,l);
Q1.insert(p2,DB(furthestson[root[p2]])+dist(w1,pos[p2]));
p2=next(p2);
}
else
{
DB l=dist(w1,pos[p1]);
Q1.add-=l;
DB v1=Q1.maxv(),v2=Q2.maxv();
upmin(ans,max(v1,v2+l));
upmin(ans,max(v2,v1+l));
if(v1<=(v1+l+v2)/2.0 && (v1+l+v2)/2.0<=v1+l) upmin(ans,(v1+l+v2)/2.0);
Q1.erase(p1);
Q2.add+=l;
move(w1,l);
move(w2,l);
h[p1]=max(Q1.maxv(),Q2.maxv());
Q2.insert(p1,DB(furthestson[root[p1]])+dist(pos[p1],w1));
p1=next(p1);
vis[p1]++;
}
} inline void solve3()
{
int i;
re(i,,now)
{
int u=edge[i].u,v=edge[i].v;DB l=DB(edge[i].dis);
if(id[u]!= && id[v]!=)continue;
if(dep[u]>dep[v]) swap(u,v);
DB v1=DB(furthestson[v]),v2=max(DB(f[v])-l,DB(dep[u])+h[id[st[u]]]);
upmin(ans,max(v1,v2+l));
upmin(ans,max(v2,v1+l)); if(v1<=(v1+l+v2)/2.0 && (v1+l+v2)/2.0<=v1+l) upmin(ans,(v1+l+v2)/2.0);
}
} int main()
{
/*freopen("foodshop.in","r",stdin);
freopen("foodshop.out","w",stdout);*/
int i;
N=gint();
now=-;mmst(first,-);
re(i,,N)
{
int u=gint(),v=gint(),dis=gint();
addedge(u,v,dis);
addedge(v,u,dis);
}
findround();
mmst(vis,);
re(i,,cnt)solve1(root[i]);
ans=1e60;
solve2();
solve3();
PF("%0.1lf\n",ans);
return ;
}