If it's a tree then the answer is obviously diameter/2
But now it's a ring-set tree, so you just enumerate through each side of the ring and delete it and ask for the diameter to be spicy (obviously you're not going to be on one side of the ring.)
And then you ask for the remaining diameter of the tree, and then the n^2 will explode.
We maintain the longest chain s of the tree with the nodes rooted in the ring
The two-point distance on the ring can be prefixed and processed (assuming that the first edge of the enumeration is the edge of the first and last point on the ring so that it can be prefixed and represented)
The diameter is Max (Sum[j]-sum[i]+s[i]+s[j])
Use a line tree to maintain sum[i]-s[i] and Sum[i] + s[i]
But I, J can not be the same, so in the segment tree to maintain a second large value can be
When you delete the edges, modify the sum array to modify the segment tree.
#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> #include <
queue> #define SF scanf #define PF printf #define LS (i<<1) #define RS (i<<1|1) using namespace std;
typedef long Long LL;
inline int read () {int x = 0, f = 1; char ch = getchar ();
while (Ch < ' 0 ' | | ch > ' 9 ') {if (ch = = '-') f =-1; ch = GetChar ();}
while (Ch >= ' 0 ' && ch <= ' 9 ') {x = x * + ch-' 0 '; ch = GetChar ();}
return x * F;
} const int MAXN = 100000; struct Node {int v, WT, next;}
EDGE[MAXN*2+10];
int adj[maxn+10], ecnt;
void Addedge (int u, int v, int wt) {Node &e = edge[++ecnt]; E.V = v; e.wt = WT; E.next = Adj[u];
Adj[u] = ecnt;
} bool Iscir[maxn+10];
LL sum[maxn+10], dis[maxn+10], d[maxn+10], ld[maxn+10], rd[maxn+10], tot, ans, MX;
int cc, CIR[MAXN+10], fa[maxn+10], vis[maxn+10], N, p;
struct Seg_tree {LL mx1[maxn*4+10], mx2[maxn*4+10];
int p1[maxn*4+10], p2[maxn*4+10]; void Up (inT i) {if (Mx1[ls] > Mx1[rs]) {mx1[i] = Mx1[ls];
P1[i] = P1[ls];
Mx2[i] = Mx1[rs];
P2[i] = P1[rs];
} else {Mx1[i] = Mx1[rs];
P1[i] = P1[rs];
Mx2[i] = Mx1[ls];
P2[i] = P1[ls];
} if (Mx2[ls] > Mx2[i]) {mx2[i] = Mx2[ls];
P2[i] = P2[ls];
} if (Mx2[rs] > Mx2[i]) {mx2[i] = Mx2[rs];
P2[i] = P2[rs];
}} void build (int i, int l, int r) {if (L = = r) {Mx1[i] = Sum[l] + dis[l]; p1[i] = l;
Mx2[i] = P2[i] = 0;
return;
} int mid = L+r >> 1;
Build (LS, l, mid);
Build (RS, mid+1, R);
Up (i);
} void ins (int i, int x, LL v, int L = 1, int R = cc) {if (L = = R) {Mx1[i] = V;
return;
} int mid = L+r >> 1; if (x <= mid) ins (LS, X, V, L, mid);
else ins (rs, X, V, mid+1, R);
Up (i);
}} T;
struct Seg_tree2 {LL mx1[maxn*4+10], mx2[maxn*4+10];
int p1[maxn*4+10], p2[maxn*4+10];
void up (int i) {if (Mx1[ls] > Mx1[rs]) {mx1[i] = Mx1[ls];
P1[i] = P1[ls];
Mx2[i] = Mx1[rs];
P2[i] = P1[rs];
} else {Mx1[i] = Mx1[rs];
P1[i] = P1[rs];
Mx2[i] = Mx1[ls];
P2[i] = P1[ls];
} if (Mx2[ls] > Mx2[i]) {mx2[i] = Mx2[ls];
P2[i] = P2[ls];
} if (Mx2[rs] > Mx2[i]) {mx2[i] = Mx2[rs];
P2[i] = P2[rs];
}} void build (int i, int l, int r) {Mx1[i] = mx2[i] = -10000000000000000LL;
if (L = = r) {Mx1[i] = Dis[l]-sum[l]; p1[i] = l;
return;
} int mid = L+r >> 1;
Build (LS, l, mid);
Build (RS, mid+1, R); Up (i);
} void ins (int i, int x, LL v, int L = 1, int R = cc) {if (L = = R) {Mx1[i] = V;
return;
} int mid = L+r >> 1;
if (x <= mid) ins (LS, x, V, L, mid);
else ins (rs, X, V, mid+1, R);
Up (i);
}} Q;
bool Dfs (int u, int pre) {fa[u] = pre;
Vis[u] = 1;
for (int i = adj[u]; i; i = edge[i].next) {int v = EDGE[I].V;
if (v = = pre) continue;
if (Vis[v]) {cir[1] = V;
FA[V] = u;
return true;
} if (Dfs (v, u)) return true;
} return false;
} void Find_circle () {DFS (1, 0);
int u = cir[1];
while (Fa[u]! = cir[1]) {CIR[++CC] = Fa[u];
U = fa[u];
} for (int i = 1; I <= cc; i++) {Iscir[cir[i]] = true;
for (int j = Adj[cir[i]]; j; j = edge[j].next) {int v = edge[j].v, wt = EDGE[J].WT;
if (v = = cir[i%cc+1]) {ld[i] = rd[i%cc+1] = WT; tot + = WT;
Break
}}} for (int i = 2; I <= cc; i++) sum[i] = Sum[i-1] + rd[i];
} void DFS (int u, int pre) {for (int i = adj[u]; i; i = edge[i].next) {int v = edge[i].v, wt = EDGE[I].WT;
if (v = = Pre | | iscir[v]) continue;
D[V] = d[u] + wt;
if (D[v] > d[p]) p = v;
DFS (V, u);
}} void Find_dis (int x) {int tmp;
D[CIR[X]] = p = 0;
DFS (Cir[x], 0);
TMP = P;
DIS[X] = d[p];
Iscir[cir[x]] = false;
D[TMP] = p = 0;
DFS (tmp, 0);
ans = max (ans, d[p]);
ISCIR[CIR[X]] = true;
} int main () {n = read ();
for (int i = 1; I <= n; i++) {int u, v, wt; U = Read (); v = read ();
wt = read (); Addedge (U, v, wt);
Addedge (V, u, wt);
} find_circle ();
for (int i = 1; I <= cc; i++) Find_dis (i);
T.build (1, 1, CC);
Q.build (1, 1, CC);
LL ANS = 10000000000000000LL; for (int i = 1; I <= cc; i++){if (t.p1[1]! = q.p1[1]) ANS = min (ans, t.mx1[1] + q.mx1[1]);
else ANS = min (ans, max (t.mx1[1]+q.mx2[1], t.mx2[1]+q.mx1[1])); Sum[i] = Rd[i] + sum[(i>1)?
(i-1): CC];
T.ins (1, I, Dis[i]+sum[i], 1, CC);
Q.ins (1, I, Dis[i]-sum[i], 1, CC);
} PF ("%.1lf\n", (double) max (ans, ans)/(double) 2.0); }