zoukankan      html  css  js  c++  java
  • 2019ICPC徐州站M题

    前天在复现赛开M自闭两天,全网找不到题解,后来偶遇cometoj群中的Acmer帮我解决困惑,在此匿名感谢qq名称为不好好学习不改名同学,以下思路均由他提供,也希望为后来人提供一定的思路和想法

    题解: 首先很容易看出这是道求树的重心的问题,但是由于他要求所有子树的重心,所以暴力求解会超时,因此我们需要进行剪枝,剪枝需要几点性质

    1.两个树合并之后树的重心在之前两棵树重心的连线路径上。

    2.如果子树的节点数大于父树节点树的一半,那么父树重心可以由该子树转移而来,因为重心的意义就是代表除去该点后最大联通子树的节点数的最小值,所以我们把子树的节点数*2-父树的节点数作为贡献度,大于0就能转移。

    然后就能做啦,注意的一点是,一棵树有可能有两个重心,两个重心必定相邻,因此只需要考虑当贡献度为0的时候就是两个答案。

    复杂度因为我并不擅长求复杂度,但是据说是O(N)的

    代码如下,代码中也有注释:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<functional>
    #include<string>
    #include<algorithm>
    #include<iostream>
    #include<set>
    #include<vector>
    #include<queue>
    using namespace std;
    const int N=4*1e5+10;
    const int inf=0x3f3f3f3f;
    int e[N],ne[N],idx;
    int h[N];
    int res[N];
    int res1[N];
    int size[N];
    int p[N];
    void add(int a,int b){
        e[idx]=b,ne[idx]=h[a],h[a]=idx++;
    }
    void dfs(int u,int fa){
        size[u]=1;//初始个数为0 
        res[u]=u;//初始化节点重心为自身,因为如果不能从子树重心转移过来,那这个树的重心就是自己 
        int son=0;
        int i;
        for(i=h[u];i!=-1;i=ne[i]){
            int j=e[i];
            if(j==fa)
            continue;
            p[j]=u;//j的父亲是u 
            dfs(j,u);
            size[u]+=size[j];//计算节点总数 
            if(size[j]>size[son])// 计算哪个是重(zhong)子树 
            son=j;
        }
        // 如果符合条件就转移 
        if(size[son]*2-size[u]>=0){
            res[u]=res[son];
            while(size[u]-2*size[res[u]]>0)
            res[u]=p[res[u]];  //通过迭代的方式往上走一格 
            if(size[u]==2*size[res[u]]&&res[u]!=u){
                res1[u]=p[res[u]];
            }
        }
    }
    int main(){
        int m,n;
        cin>>n;
        int i;
        memset(h,-1,sizeof h);
        for(i=0;i<n-1;i++){
            int a,b;
            scanf("%d%d",&a,&b);
            add(a,b);
            add(b,a);
        }
        p[1]=1;
        dfs(1,-1);
        for (int i = 1; i <= n; i ++){
        
            if(!res1[i])
            printf("%d ", min(res1[i], res[i]);
            printf("%d\n", max(res1[i], res[i]);
        }
        
    }
    View Code
  • 相关阅读:
    设计模式——原型链模式之在原型上设置属性
    设计模式——原型链模式
    设计模式——构造函数模式
    设计模式——工厂模式
    设计模式——单例模式
    为什么做java的web开发我们会使用struts2,springMVC和spring这样的框架?(转载)
    Unity3d中设置UISprite图片灰显方法
    游戏后端主程工作内容及游戏项目中的注意事项及游戏项目中注意事项<转载>
    xcode使用
    ios学习笔记2
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12010370.html
Copyright © 2011-2022 走看看