• [每日一题]: CodeForces 685B Kay and Snowflake


    题目:

    题目大意:

    给一棵树,接着给一个节点,作为一棵子树的根节点,问以这个节点为根的树的重心是多少?
    

    树的重心不了解的戳这里:

    https://www.cnblogs.com/prjruckyone/p/12793007.html

    侃侃:

    这道题问的比较清晰易懂,但是实现起来较有难度,主要是利用树形 DP 的思想。
    由底向上得到信息,如果这道题查询范围较小的话,我们可以直接利用树的重心
    的板子进行求解即可,但是这道题查询的数据范围较大,查询的话时间肯定会崩的。
    本菜鸡就亲身尝试了,哈哈。
    这里就需要用到 树的重心中的几个性质进行优化。
    

    本题用到的几个性质:

    1、把两棵树通过一条边相连,新的树的重心在原来两棵树重心的连线上。
    (一个节点也是一棵树,所以我们递归到最深处,两个节点就是两棵树
    然后就可以用这个性质了,一个节点的重心即它本身)
    2、以这个点为根,那么所有的子树(不算整个树自身)的大小都不超过
    整个树大小的一半。
    我们就可以根据这个性质进行自底向上更新。
    

    Code:

    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    const int maxn = 3e5 + 10;
    
    int h[maxn],ve[maxn],Ne[maxn],e[maxn];
    int vis[maxn],Size[maxn],fa[maxn];
    
    int n,q;
    int tot,u,v;
    int center[maxn],min_port,pos;
    
    void add(int u,int v) {
    	ve[++ tot] = v;
    	Ne[tot] = h[u];
    	h[u] = tot;
    	return ;
    }
    
    void DFS(int x,int f) {
    	Size[x] = 1;
    	// 到叶节点时一定是它自己 
    	if(h[x] == Ne[h[x]]) {
    		center[x] = x;
    		return ;
    	} 
    	
    	int max_port = 0,pos = 0;
    	// 寻找 以 x 为根的最大子树的 根节点 
    	for(int i = h[x]; i; i = Ne[i]) {
    		int y = ve[i];
    		if(y == f) continue;
    		DFS(y,x);
    		Size[x] += Size[y];
    		if(Size[y] > max_port) {
    			pos = y;
    			max_port = Size[y];
    		}
    	}
    	center[x] = center[pos];
    	// 以重心为根,那么所有的子树的大小都不超过整个树大小的一半 
    	while(Size[center[x]] * 2 <= Size[x]) {
    		center[x] = fa[center[x]];	
    	}
    	return ;
    }
    
    int main(void) {
    	scanf("%d%d",&n,&q);
    	for(int i = 2; i <= n; i ++) {
    		scanf("%d",&v);
    		fa[i] = v;
    		add(v,i);
    //		add(i,v);
    	}
    	int st = 0;
    	DFS(1,-1);
    	while(q --) {
    		scanf("%d",&st);
    		printf("%d
    ",center[st]);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    高进度乘法FFT优化
    Activity的四种加载模式
    异步任务AsyncTask
    利用Handler在子线程中更新UI
    Android 屏幕旋转监听
    HDOJ-1698-线段树成段更新
    HDOJ-1671-字典树
    HDOJ-1251 字典树
    python数据结构与算法
    find the lowest number location
  • 原文地址:https://www.cnblogs.com/prjruckyone/p/12796413.html
Copyright © 2020-2023  润新知