由于每个点都要连一个边。
最终图会分成若干个联通块,每个联通块n个点,n条边。即是一个基环树。
求出每个联通块中任意两点距离最大值(即基环树的直径)求和即可。
一般基环树的问题围绕环来处理。
先把环看出一个点,就能转化为树上问题。
基环树的直径分两类:(把环当成根节点)
1.不在环上,在环的某个节点的子树中。
2.经过环上2点x,y。并延申至x,y所在子树。即dis(x,y)+D[x]+D[y] .D[x]为dp求直径时维护的,x到其子树中点的最远距离。
我们先求出基环树的环 :s1,s2,s3……s_nm
然后环上每个点做为根节点,执行树形dp,求出与其连接的非环点构成的子树最大直径。并维护出D[x].
这样第一类直径就求出来了。
第二类直径转化为了:
一个环上有nm个点,任意两个点的距离已知,求出最大的f(x,y),f(x,y)=d[x]+d[y]+dist(x,y);
我们可以把环拓展一倍,变成长度为nm*2的区间。
用sm[y]-sm[x]表示dist(x,y),sm[x]即前缀相邻距离和
然后枚举(x,y)区间的右端点,d[y]+sm[y]已知,求左端点x,使得d[x]-sm[x]最大。且y-x<=n (不能经过一个点2次,这样遍历完,x->y顺时针和逆时针的走法都能遍历到)
这里可以用单调队列维护即可。(队列里维护 d[i]-sm[i] 递减,右边的数如果大,那么左边的数肯定就永远选不到了)