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);
}
posted @ 2019-07-13 14:20 蒟蒻--lichenxi 阅读(...) 评论(...) 编辑 收藏