CF1179D Fedor Runs for President
传送门
首先应该考虑一下,多加一条边对树上路径的影响是什么
可以发现多加一条边就会出现一颗基环树
我们发现所有经过环的路径都会翻倍
那么假设\(x\)是\(y\)的父亲,\(x\)在环内,那么将\(y\)加入环的贡献就是\((size[x]-size[y])*size[y]\)
然后类似求树的直径做两遍\(bfs\)(严格证明我也不会)
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
#define rg register
void read(int &x){
char ch;bool ok;
for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
}
const int maxn=5e5+10;
int pps,size[maxn],n,pre[maxn*2],nxt[maxn*2],h[maxn],cnt,len;
long long ans,now,f[maxn];
void add(int x,int y){
pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt;
pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt;
}
void dfs(int x,int fa){
size[x]=1;
for(rg int i=h[x];i;i=nxt[i])
if(pre[i]!=fa)dfs(pre[i],x),size[x]+=size[pre[i]];
}
void bfs(int now){
memset(f,0,sizeof f);
queue<int>q;q.push(now);
while(!q.empty()){
int x=q.front();q.pop();
for(rg int i=h[x];i;i=nxt[i])
if(!f[pre[i]])f[pre[i]]=f[x]+1ll*(size[x]-size[pre[i]])*size[pre[i]],q.push(pre[i]);
if(f[x]>f[pps])pps=x;
}
}
int main(){
read(n);
for(rg int i=1,x,y;i<n;i++)read(x),read(y),add(x,y);
now=1ll*n*(n-1)/2,dfs(1,0),bfs(1),dfs(pps,0),bfs(pps);
ans=max(1ll*f[pps]+now,ans);
printf("%lld\n",ans);
}