rt
思路是单调队列,LOJ 1 WA 3 RE,Luogu 2 WA 2 RE
(主要WA我还能接受但是RE不知道为什么,调了一下发现是在找环的部分但我并没发现有什么会影响的)
QwQ
#include<bits/stdc++.h>
#define rep(i,a,b) for(ll i=(a);i<=(b);i++)
#define per(i,a,b) for(ll i=(a);i>=(b);i--)
#define op(x) ((x&1)?x+1:x-1)
#define odd(x) (x&1)
#define even(x) (!odd(x))
#define lc(x) (x<<1)
#define rc(x) (lc(x)|1)
#define mid(x) ((l[x]+r[x])>>1)
#define lowbit(x) (x&-x)
#define Max(a,b) (a>b?a:b)
#define Min(a,b) (a<b?a:b)
#define next Cry_For_theMoon
#define il inline
#define pb(x) push_back(x)
#define is(x) insert(x)
#define sit set<int>::iterator
#define mapit map<int,int>::iterator
#define pi pair<int,int>
#define ppi pair<int,pi>
#define pp pair<pi,pi>
#define fr first
#define se second
#define vit vector<int>::iterator
#define mp(x,y) make_pair(x,y)
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef double db;
using namespace std;
const ll MAXN=1e5+10,MAXM=2e5+10,INF=1e16;
ll n,a,b,l,ans,ans2=INF;
struct Edge{
ll u,v,w;
}edge[MAXM];
ll first[MAXN],next[MAXM],tot;
ll fa[MAXN],r[MAXN],rv[MAXN],cnt;
ll tag[MAXN],top[MAXN],depth[MAXN],maxdepth[MAXN];
ll sum[MAXN],suf[MAXN],lim[MAXN];
pi pre[MAXN];
int Find(int x){
if(fa[x]==x)return x;
return fa[x]=Find(fa[x]);
}
void addedge(int u,int v,int w){
edge[++tot].u=u;edge[tot].v=v;edge[tot].w=w;
next[tot]=first[u];first[u]=tot;
}
void findRing(int u){
if(u==b){
r[++cnt]=b;rv[cnt]=pre[b].se;
int tmp=b;
while(tmp!=a){
r[++cnt]=pre[tmp].fr;rv[cnt]=pre[pre[tmp].fr].se;
tmp=pre[tmp].fr;
}
return;
}
for(int j=first[u];j;j=next[j]){
int v=edge[j].v;
if(v==pre[u].fr)continue;
pre[v]=mp(u,edge[j].w);
findRing(v);
}
}
void outTree(int u){
ll max1=-INF,max2=-INF;
for(int j=first[u];j;j=next[j]){
int v=edge[j].v;
if(tag[v] || v==top[u])continue;
top[v]=u;
depth[v]=depth[u]+edge[j].w;
outTree(v);
maxdepth[u]=Max(maxdepth[u],maxdepth[v]+edge[j].w);
if(maxdepth[v]+edge[j].w>max1)max2=max1,max1=maxdepth[v]+edge[j].w;
else if(maxdepth[v]>max2)max2=maxdepth[v]+edge[j].w;
}
ans=Max(ans,Max(max1,max1+max2));
}
ll q1[MAXM],q2[MAXM],head1,rear1,head2,rear2;
int main(){
scanf("%lld",&n);
rep(i,1,n)fa[i]=i;
rep(i,1,n){
scanf("%lld%lld%lld",&a,&b,&l);
if(Find(a)==Find(b)){
//断环成链
findRing(a);
rv[cnt]=l;
continue;
}
fa[Find(a)]=Find(b);
addedge(a,b,l);addedge(b,a,l);
}
//计算每一个外向树的答案
rep(i,1,cnt)tag[r[i]]=1;
rep(i,1,cnt){
int rt=r[i];
outTree(rt);
}
rep(i,1,cnt)r[i+cnt]=r[i],rv[i+cnt]=rv[i];
cnt*=2;
rep(i,1,cnt)sum[i]=sum[i-1]+rv[i-1];
//维护前n个d+sum的最大值,d-sum的最大值
rep(i,1,cnt){
while(head1<rear1 && q1[head1]+(cnt/2)<=i)head1++;
while(head2<rear2 && q2[head2]+(cnt/2)<=i)head2++;
while(head1<rear1 && sum[q1[rear1-1]]+maxdepth[r[q1[rear1-1]]]<sum[i]+maxdepth[r[i]])rear1--;
q1[rear1++]=i;
if(head1<rear1 && head2<rear2 && i>(cnt/2)){
int R=q1[head1],L=q2[head2];
//[L,R]这一段
if(L!=R){ans2=Min(ans2,maxdepth[r[L]]+maxdepth[r[R]]+sum[R]-sum[L]);}
else{
ll tmp=0;
if(head1+1<rear1){
R=q1[head1+1];
tmp=Max(tmp,maxdepth[r[L]]+maxdepth[r[R]]+sum[R]-sum[L]);
// printf("[%d,%d] %d\n",L,R,maxdepth[r[L]]);
}
if(head2+1<rear2){
L=q2[head2+1],R=q1[head1];
tmp=Max(tmp,maxdepth[r[L]]+maxdepth[r[R]]+sum[R]-sum[L]);
// printf("[%d,%d] %d\n",L,R,maxdepth[r[L]]);
}
// printf("tmp:%lld\n",tmp);
ans2=Min(ans2,tmp);
}
}
while(head2<rear2 && maxdepth[r[q2[rear2-1]]]-sum[q2[rear2-1]] < maxdepth[r[i]]-sum[i])rear2--;
q2[rear2++]=i;
}
ans=Max(ans,ans2);
printf("%.1f\n",(double)(ans)/2);
return 0;
}