题意
给n个点,以及n-2条边,意思是给出两棵树,找到两个点连接,使得这棵树上的每个点到另一个点的经过的边的之和为最小值
题解
根据自己的数据1-2 2-3 4-5 5-6可以得出求两个树的重心连接,然后树形dp直接得出答案,先用并查集得出两个树的点数和归属,然后连成一棵树,然后用边权算贡献==子节点*其余的节点数之和
树的重心模板
void dfs1(int r){
vis[r]=1;
sz[r]=1;
int tmp=0;
for(int i=head[r];~i;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]){
dfs1(v);sz[r]+=sz[v];
tmp=max(tmp,sz[v]);
}
}
tmp=max(tmp,n1-sz[r]);
if(tmp<sz0){
zx1=r;
sz0=tmp;
}
}
ac代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define pii pair<int,int>
#define mak(a,b) make_pair(a,b)
#define mem(a,b) memset(a,b,sizeof(a))
#define mod 1000000007
const double pi=acos(-1.0);
const int N=1e5+10;
int F[N],ge[N];
int findd(int x){return F[x]==x?x:F[x]=findd(F[x]);}
int sz[N],zx1,zx2,head[N],tot,n,n1,n2,vis[N],sz2[N],sz0;
ll ans;
struct{
int to,next;
}edge[N*2];
void add(int u,int v){
edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
edge[tot].to=u;edge[tot].next=head[v];head[v]=tot++;
}
void inint(){
mem(head,-1);tot=0;
for(int i=1;i<=n;i++){
F[i]=i;ge[i]=1;
}
zx1=-1,zx2=-1;ans=0;
}
void dfs1(int r){
vis[r]=1;
sz[r]=1;int tmp=0;
for(int i=head[r];~i;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]){
dfs1(v);sz[r]+=sz[v];
tmp=max(tmp,sz[v]);
}
}
tmp=max(tmp,n1-sz[r]);
if(tmp<sz0){
zx1=r;
sz0=tmp;
}
}
void dfs2(int r){
vis[r]=1;
sz[r]=1;int tmp=0;
for(int i=head[r];~i;i=edge[i].next){
int v=edge[i].to;
if(!vis[v]){
dfs2(v);sz[r]+=sz[v];
tmp=max(tmp,sz[v]);
}
}
tmp=max(tmp,n2-sz[r]);
if(tmp<sz0){
zx2=r;
sz0=tmp;
}
}
void dfs(int u,int fa){
sz[u]=1;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;if(fa==v){continue;}
dfs(v,u);
sz[u]+=sz[v];
}
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to;if(fa==v){continue;}
ans+=(ll)(n-sz[v])*sz[v];
}
}
int main(){
while(~scanf("%d",&n)){
inint();
for(int i=0;i<n-2;i++){
int u,v;scanf("%d%d",&u,&v);add(u,v);
int uu=findd(u),vv=findd(v);
if(uu!=vv){
F[uu]=vv;ge[vv]+=ge[uu];
}
}
int s1=-1,s2;
for(int i=1;i<=n;i++){
if(F[i]==i && s1==-1){
s1=i;n1=ge[i];
}
else if(F[i]==i && s1!=-1){
s2=i;n2=ge[i];
}
}
mem(vis,0);sz0=inf;
dfs1(s1);
mem(vis,0);sz0=inf;
dfs2(s2);//cout<<zx1<<zx2<<endl;
add(zx1,zx2);
dfs(1,0);
printf("%lld
",ans);
}
return 0;
}