2024.2.25模拟赛T2题解
枚举根之后,考虑每次连边的贡献,通过贡献算出每个点的权值,每次找出权值最大的点,又要保证父亲在儿子之前,所以将父亲和儿子合并,权值也合并一下即可
code
#include<bits/stdc++.h>
using namespace std;
#define N 2005
int ans,n,k;
int sz[N],deg[N],du[N],fu[N],f[N],h[N];
struct AB{
int a,b,n;
}d[N*2];
void cun(int x,int y){
d[++k]=(AB){x,y,h[x]},h[x]=k;
}
struct A{
int x,y,z;
};
bool operator < (A x,A y){
return x.z*y.y<x.y*y.z;
}
priority_queue<A> q;
void dfs(int x,int fa){
sz[x]=1,deg[x]=du[x]-2,fu[x]=fa;
for(int i=h[x];i;i=d[i].n){
int y=d[i].b;
if(y==fa) continue;
dfs(y,x);
}
}
int find(int x){
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
int solve(int rt){
int ans=0;
dfs(rt,0);deg[rt]+=2;
for(int i=1;i<=n;i++){
f[i]=i;
if(i!=rt) q.push({i,sz[i],deg[i]});
}
while(!q.empty()){
A p=q.top();q.pop();
if(sz[p.x]!=p.y) continue;
int fa=find(fu[p.x]),x=p.x;
assert(x);
ans+=sz[x]*deg[fa],sz[fa]+=sz[x],deg[fa]+=deg[x],f[find(x)]=fa;
if(fa!=rt) q.push({fa,sz[fa],deg[fa]});
}
return ans;
}
int main(){
scanf("%d",&n);
for(int i=1,x,y;i<n;i++){
scanf("%d%d",&x,&y);
x++,y++;
cun(x,y),cun(y,x),du[x]++,du[y]++;
}
for(int i=1;i<=n;i++){
ans=max(ans,solve(i));
}
printf("%lld\n",ans+n-1);
return 0;
}

浙公网安备 33010602011771号