zoukankan      html  css  js  c++  java
  • cf 686D

    题意让你求每个子树的重心

    直接求肯定不行对吧......然后又是在树上

    考虑树的重心的性质

    1.任意一个子树小于当前树的二分之一     (换句话  一棵树的重心一定是自己或者是重儿子子树上)

    2.当两个子树连接的时候新接成的树的重心一定在  两个子树重心的路径上

    然后发现.....这个题  可以直接分治   跑  然后就没了

    嘛....主要我不会写....(就是那种似懂非懂.....原理知道,但不会操作的感觉....)

    关键就在于合并.,,,

    只要递归搞到子树的重心....然后逐步往上跳  直至满足与当前树合并为重心.....

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define MAXN 300005
    using namespace std;
    
    int n,q,tot;
    int h[MAXN],ans[MAXN],f[MAXN],sz[MAXN];//以u为根的子树的重心  各点父亲  子树大小 
    
    struct node{
        int from,to,next;
    }e[MAXN<<1];
    
    void init(){
        memset(h,-1,sizeof(h));
        memset(sz,0,sizeof(sz));
    }
    
    void add(int x,int y){
        tot++;
        e[tot].from=x;
        e[tot].to=y;
        e[tot].next=h[x];
        h[x]=tot;
    }
    
    int dfs(int now,int fa){
        f[now]=fa;
        sz[now]=1;
        ans[now]=now;
        for(int i=h[now];i!=(-1);i=e[i].next){
            if(e[i].to!=fa){
                dfs(e[i].to,now);
                sz[now]+=sz[e[i].to];
            }
        }
        for(int i=h[now];i!=(-1);i=e[i].next){
            if(e[i].to!=fa&&sz[e[i].to]*2>sz[now]){
                ans[now]=ans[e[i].to];
            }
        }
        while((sz[now]-sz[ans[now]])*2>sz[now]){
            ans[now]=f[ans[now]];
        }
    }
    
    
    int main(){
        cin>>n>>q;init();
        for(int i=2;i<=n;i++){
            int p;cin>>p;
            add(i,p);
            add(p,i);
        }    
        dfs(1,1);
        for(int i=1;i<=q;i++){
            int p;cin>>p;
            cout<<ans[p]<<endl;
        }
    }
    View Code
  • 相关阅读:
    SqlServer 中的递归查询
    javascript 个人笔记
    WPF图片切换问题(美女时钟)
    在winform如何避免绘图时图片总是闪烁
    SQLServer中几种行列转换的方式
    Oracle递归查询
    Autofac整合Castle.DynamicProxy实现AOP
    学习Nop中Routes的使用
    TypeFinder学习
    集成和配置AutoMapper
  • 原文地址:https://www.cnblogs.com/shatianming/p/12297296.html
Copyright © 2011-2022 走看看