• codeforces 685 B (求所有子树重心)


    sz[x]代表以x为根的子树大小,hs[x]代表以x为根的重儿子,kp[x]代表以x为根的重心。树的重心有如下结论:x的重心在其重儿子的重心到x的这条链上,即kp[hs[x]]到x的这条链上。所以从kp[hs[x]]向上枚举至x。如果枚举到节点g满足:sz[hs[g]] * 2 <= sz[x] && (sz[x] - sz[g]) * 2 <= sz[x]则该点即为以x为根的子树的重心。

    #include <bits/stdc++.h>
    #include <unordered_map>
    using namespace std;
    #define maxn 300010
    #define ios cin.tie(0) ,cout.tie(0), cout.sync_with_stdio(0)
    typedef long long ll;
    struct edge{
        int v,nxt;
    }e[maxn];
    int head[maxn],en;
    int hs[maxn],sz[maxn],kp[maxn];
    int fa[maxn];
    void init(){
        en=0;memset(head,-1,sizeof(head));
    }
    void adde(int u,int v){
        e[++en].v=v;e[en].nxt=head[u];head[u]=en;
    }
    void dfs(int x){
        //printf("x=%d
    ",x);
        sz[x]=1;kp[x]=x;int sw=0;
        for(int i=head[x];i!=-1;i=e[i].nxt){
            int v=e[i].v;
            dfs(v);sz[x]+=sz[v];
            if(sw<sz[v])hs[x]=v,sw=sz[v];
        }
        int p=kp[hs[x]];
        while(p&&p!=fa[x]){
            //printf("p=%d
    ",p);
            if(sz[hs[p]]*2<=sz[x]&&(sz[x]-sz[p])*2<=sz[x]){
                kp[x]=p;break;
            }
            p=fa[p];
        }
    }
    int main(){
        init();
        int n,q;scanf("%d%d",&n,&q);
        for(int i=2;i<=n;i++){
            scanf("%d",&fa[i]);adde(fa[i],i);
        } 
        dfs(1);
        while(q--){
            int x;scanf("%d",&x);printf("%d
    ",kp[x]);
        }
        return 0;
    }
  • 相关阅读:
    JQuery高级
    Filter&Listener
    关于用户信息的一个综合案例
    JSP,EL和JSTL
    Cookie和Session
    Request和Response
    Servlet和HTTP请求协议
    Tomcat
    xml
    数组模拟堆
  • 原文地址:https://www.cnblogs.com/cleanerhgf/p/11986537.html
Copyright © 2020-2023  润新知