F. Dominant Indices Educational Codeforces Round 47 (Rated for Div. 2)(树上启发式合并)

本文介绍了一种针对树形结构的数据处理算法,通过定义深度数组来表达节点间的关系,并提出了主导索引的概念来衡量节点的重要性。算法首先进行深度优先搜索以计算每个节点的深度数组,随后递归地计算每个节点的主导索引。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

F. Dominant Indices
time limit per test
4.5 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

You are given a rooted undirected tree consisting of n
vertices. Vertex 1

is the root.

Let’s denote a depth array of vertex x
as an infinite sequence [dx,0,dx,1,dx,2,…], where dx,i is the number of vertices y

such that both conditions hold:

x

is an ancestor of y
;
the simple path from x
to y traverses exactly i

edges. 

The dominant index of a depth array of vertex x
(or, shortly, the dominant index of vertex x) is an index j

such that:

for every k<j

, dx,k

#include<bits/stdc++.h>
#define LL long long
#define INF 0x3f3f3f3f
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
const int maxn = 1e6+6;
int siz[maxn];
int son[maxn];
int skip[maxn];
int n;
int dep[maxn];
int head[maxn];
int tot;
LL ans[maxn];
LL cnt[maxn];
struct node
{
    int u,v;
    int net;
}E[maxn*2];
void init()
{
    memset(head,-1,sizeof(head));
    tot = 0;
}
void build(int u,int v)
{
    E[tot].u = u;
    E[tot].v = v;
    E[tot].net = head[u];
    head[u] =  tot++;
}
void dfs0(int u,int fa,int deep)
{
    siz[u] = 1;
    dep[u] = deep;
    for(int i = head[u];~i;i = E[i].net){
        int v = E[i].v;
        if(v==fa){
            continue;
        }
        dfs0(v,u,deep+1);
        siz[u]+=siz[v];
        if(siz[son[u]]<siz[v]){
            son[u] = v;
        }
    }
}
LL mx = 0;
LL sum = 0;
void getans(int u,int fa,int vv,int uu)
{
    //cout<<uu<<' '<<u<<endl;
    cnt[dep[u]]+=vv;
    if(vv>0&&cnt[dep[u]]>mx){
        mx = cnt[dep[u]];
        sum = dep[u];
    }
    else if(vv>0&&cnt[dep[u]]==mx){
        sum = min(sum,(LL)dep[u]);
    }
    for(int i = head[u];~i;i = E[i].net){
        if(E[i].v==fa||skip[E[i].v]) continue;
        getans(E[i].v,u,vv,uu);
    }
}
void dfs(int u,int fa,int op)
{
  //  cout<<u<<endl;
    for(int i = head[u];~i;i = E[i].net){
        int v = E[i].v;
        if(v==fa||v==son[u]) continue;
        dfs(v,u,0);
    }
    if(son[u]){
        dfs(son[u],u,1);
        skip[son[u]] = 1;
    }
    getans(u,fa,1,u);
    ans[u] = sum-dep[u];
    if(son[u]){
        skip[son[u]] = 0;
    }
    if(op==0){
        getans(u,fa,-1,u);
        sum = mx = 0;
    }
}
int main()
{
    init();
    scanf("%d",&n);
    for(int i = 0;i<n-1;i++){
        int u,v;
        scanf("%d%d",&u,&v);
        build(u,v);
        build(v,u);
    }
    dfs0(1,0,1);
    dfs(1,0,1);
    for(int i = 1;i<=n;i++){
        printf("%lld\n",ans[i]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值