hdu 6567 树形dp+树的重心

题意

给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;
}
原文地址:https://www.cnblogs.com/luoyugongxi/p/13748779.html