[AcWing]846. 树的重心

算法标签 dfs,树形DP

题目简叙

[AcWing]846. 树的重心_第1张图片

思路

每次寻找删除节点之后的剩余联通块最大节点
[AcWing]846. 树的重心_第2张图片

代码

#include
#include

using namespace std;

const int N=1e5+10;
int h[N],e[2*N],ne[2*N],idx;
//h头节点
//e元素 双向图 两倍数据
//ne指针 
//idx下标
int ans=N;
//ans初始化节点数量N个
bool st[N];
//布尔数组,控制是否点亮
int n,a,b;

void add(int a,int b){
    e[idx]=b,ne[idx]=h[a],h[a]=idx++;//双向链表插入
}

int dfs(int u){
	st[u]=true;//当前节点状态更改为走过
    int size=0;
    int sum=0;
    for(int i=h[u];i!=-1;i=ne[i]){//链表下探
        int j=e[i];//对应节点
        if(!st[j]){//检查如果没有走过
            int s=dfs(j);//dfs下探,s获得子树节点值
            size=max(size,s);//每一个联通块的大小的最大值
            sum+=s;//当前子树的总共的大小
        }
    }
    size = max(size, n - sum - 1);//比较当前大还是删去这个节点的联通块更大
    ans = min(ans, size);//获得两者最小值

    return sum + 1;sum+1 初始化为0 而当前这个点即根也算是该连通块内的一点
}

int main(){
    cin>>n;
    
    memset(h,-1,sizeof h);
    
    int nn=n-1;//树定义是当且仅当任何两个点之间仅有一条路径的图,所以只要是树就一定只有n-1条边
    while(nn--){
        cin>>a>>b;
        add(a,b),add(b,a);
    }
    
    dfs(1);
    
    cout<<ans<<endl;
    
    return 0;
}

AC记录

[AcWing]846. 树的重心_第3张图片

你可能感兴趣的:(树状结构,树型DP,模板题)