树的重心

题目:

代码:

1. 小数据量   时间复杂度O(n^{2})

#include<bits/stdc++.h>
using namespace std;

int pre[100005],dist[100005],cnt,f[100005];
vector<int> edge[100005];

void dfs(int x){
    for(auto y:edge[x]){
        if(y!=pre[x]){
            pre[y]=x;
            dist[y]=dist[x]+1;
            dfs(y);
        }
    }
}

void count(int x){
    cnt++;
    for(auto y:edge[x]){
        if(y!=pre[x]){
            pre[y]=x;
            count(y);
        }
    }
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    for(int i=1;i<=n;i++){
        memset(pre,0,sizeof(pre));
        f[i]=0;
        for(auto x:edge[i]){
            cnt=0;
            pre[x]=i; 
            count(x);
            f[i]=max(f[i],cnt);
        }
    }
    int inx=1<<30,x=0;
    for(int i=1;i<=n;i++){
        if(f[i]<inx){
            x=i;
            inx=f[i];
        }
    }
    memset(pre,0,sizeof(pre));
    memset(dist,0,sizeof(dist));
    dfs(x);
    int ans=0;
    for(int i=1;i<=n;i++){
        ans+=dist[i];
    }
    printf("%d",ans);
}
 

2. 大数据量  时间复杂度O( n )

#include<bits/stdc++.h>
using namespace std;

int pre[100005],dist[100005],cnt,s[100005],f[100005];
vector<int> edge[100005];

void dfs(int x){
    for(auto y:edge[x]){
        if(y!=pre[x]){
            pre[y]=x;
            dist[y]=dist[x]+1;
            dfs(y);
        }
    }
}

void solve(int x){
    s[x]=1;
    for(auto y:edge[x]){
        if(y!=pre[x]){
            pre[y]=x;
            solve(y);
            s[x]+=s[y];
        }
    }
}

int main(){
    int n;
    scanf("%d",&n);
    for(int i=1;i<n;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        edge[x].push_back(y);
        edge[y].push_back(x);
    }
    memset(pre,0,sizeof(pre));
    memset(s,0,sizeof(s));
    solve(1);
    
    int inx=1<<30,v;
    for(int i=1;i<=n;i++){
        f[i]=0;
        for(auto x:edge[i]){
            //这里的pre并不是判断是否成环,而是看以当前i点为根连到目前这条边的方向上连了多          少个节点
            if(i!=pre[x]){
                f[i]=max(f[i],s[x]);
            }else {
                f[i]=max(f[i],n-s[i]);
            }
        }
        if(f[i]<inx){
            inx=f[i];
            v=i;
        }
    }
    memset(pre,0,sizeof(pre));
    memset(dist,0,sizeof(dist));
    dfs(v);
    long long ans=0;
    for(int i=1;i<=n;i++){
        ans+=dist[i];
    }
    printf("%d",ans);
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值