zoukankan      html  css  js  c++  java
  • 树的重心 + 板子

    嘛是树的重心?

    树的重心也叫树的质心。找到一个点,其所有的子树中最大的子树节点数最少,
    那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。
    所有的子树中最大的子树节点数最少,这句话需要细细的品味。
    

    所有的子树中最大的子树节点数最少 是嘛意思?

    在求树的重心的时候,我们需要删除一个点,至于为什么要这样做,我的拙见
    是现在会求就行了,大佬们研究出来的算法就是让我们用的(不喜勿喷)。
    那么我们究竟应该删除哪个节点以满足我们的要求呢?
    
    
    我们可以按照树形 DP 的思想由下到上进行尝试,找到符合 
    所有的子树中最大的子树节点数最少 这个条件的。
    我们删除一个节点后会出现很多的分支,我们要使得这些分支中最大的最小。
    用图来解释一下:
    

    当我们删除 1 号节点时,各分支的大小为 3(3、6、7) 3(2、5、4)        最大为 3
    当我们删除 2 号节点时,各分支的大小为 1(5)   1(4)  4(1、3、6、7)   最大为 4
    
    我们要从 最大的里面找一个最小的,即删除一号节点的 3,所以这棵树的重心是 3.
    

    树的重心有嘛性质?

    树中所有点到某个点的距离和中,到重心的距离和是最小的,如果有两个距离和,他们的距离和一样。
    把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
    一棵树添加或者删除一个节点,树的重心最多只移动一条边的位置。
    一棵树最多有两个重心,且相邻。
    

    Code:

    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    const int maxn = 1e5 + 10;
    
    int head[maxn],Next[maxn],edge[maxn],ver[maxn];
    
    int Size[maxn],vis[maxn];
    
    int tot = 0,u,v;
    
    int n,min_port = INF,center;
    
    void add(int u,int v) {
    	ver[++ tot] = v,Next[tot] = head[u];
    	head[u] = tot;
    	return ;
    }
    
    void DFS(int u) {
    	// 标记,初始化每个节点的大小为 1 
    	vis[u] = 1,Size[u] = 1;
    	// 存储要删除的节点的所有的子树中最大的一颗子树的大小 
    	int max_port = 0;
    	for(int i = head[u]; i; i = Next[i]) {
    		int y = ver[i];
    		if(vis[y]) continue;
    		DFS(y);
    		// 向上走 
    		Size[u] += Size[y];
    		// 比较得到最大的 
    		max_port = max(max_port,Size[y]);
    	} 
    	// 得到删除当前节点后,节点数量最多的连通块 
    	max_port = max(max_port,n - Size[u]);
    	// 找到最大中的最小的 
    	if(max_port < min_port) {
    		min_port = max_port;
    		center = u; 
    	}
    	return ;
    }
    
    int main(void) {
    	scanf("%d",&n);
    	for(int i = 1; i < n; i ++) {
    		scanf("%d%d",&u,&v);
    		add(u,v);
    		add(v,u);
    	}
    	// 将无根树转化成有根树 
    	DFS(1);
    	printf("min_port = %d
    center = %d
    ",min_port,center);
    	return 0;
    } 
    

    测试:

    9
    1 2
    1 7
    1 4
    2 8
    2 5
    4 3
    4 6
    3 9
    


    Answer:

  • 相关阅读:
    ORA-04098 trigger 'DBBJ.DB_EV_ALTER_ST_METADATA' is invalid and failed re-validation
    ORA -04098 触发器无效且未通过重新验证
    Oracle 设置主键自增长__Oracle
    重启Oracle服务
    手动启动 oracle 服务
    oracle错误-ORA-12519, TNS:no appropriate service handler found
    ORA-00904: 标识符无效——解决方案
    [原创] 新人分享--ORA-01012:not logged on的解决办法 [复制链接]
    java验证,”支持6-20个字母、数字、下划线或减号,以字母开头“这个的正则表达式怎么写?
    全面解析JS字符串和正则表达式中的match、replace、exec等函数
  • 原文地址:https://www.cnblogs.com/prjruckyone/p/12793007.html
Copyright © 2011-2022 走看看