codeforces 1009F Dominant Indices Dsu on tree

https://codeforces.com/problemset/problem/1009/F
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<dx,j;
for every k>j, dx,k≤dx,j.
For every vertex in the tree calculate its dominant index.

Input
The first line contains one integer n (1≤n≤106) — the number of vertices in a tree.

Then n−1 lines follow, each containing two integers x and y (1≤x,y≤n, x≠y). This line denotes an edge of the tree.

It is guaranteed that these edges form a tree.

Output
Output n numbers. i-th number should be equal to the dominant index of vertex i.

Examples
Input
4
1 2
2 3
3 4
Output
0
0
0
0
Input
4
1 2
1 3
1 4
Output
1
0
0
0
Input
4
1 2
2 3
2 4
Output
2
1
0
0
题目大意:题目描述比较抽象,其实就是求一棵树中以每个节点作为根节点的子树时,该子树哪一层的节点数目最多,如果有多层节点数目都相等的话,取最浅的那一层。
思路:dsu on tree模板题,相关介绍请戳

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn=1e6+5;

struct Edge
{
    int to,nxt;
}edge[maxn<<1];

int head[maxn],siz[maxn],son[maxn],deep[maxn],cnt[maxn],ans[maxn];
int n,tot,Son,MAX,idx;

inline void addedge(int u,int v)
{
    edge[++tot].to=v,edge[tot].nxt=head[u],head[u]=tot;
}

void dfs1(int u,int f,int dep)
{
    int v;
    siz[u]=1,deep[u]=dep;
    for(int i=head[u];i;i=edge[i].nxt)
    {
        v=edge[i].to;
        if(v==f)
            continue;
        dfs1(v,u,dep+1);
        siz[u]+=siz[v];
        if(siz[v]>siz[son[u]])
            son[u]=v;
    }
}

void modify(int u,int f,int val)
{
    cnt[deep[u]]+=val;
    if(cnt[deep[u]]>MAX)
        MAX=cnt[deep[u]],idx=deep[u];
    else if(cnt[deep[u]]==MAX)
        idx=min(idx,deep[u]);
    int v;
    for(int i=head[u];i;i=edge[i].nxt)
    {
        v=edge[i].to;
        if(v==f||v==Son)
            continue;
        modify(v,u,val);
    }
}

void dfs2(int u,int f,bool tag)
{
    int v;
    for(int i=head[u];i;i=edge[i].nxt)
    {
        v=edge[i].to;
        if(v==f||v==son[u])
            continue;
        dfs2(v,u,0); //轻儿子
    }
    if(son[u])
        dfs2(son[u],u,1),Son=son[u];//重儿子
    modify(u,f,1);//递归计算子树贡献
    ans[u]=idx;//记录答案
    Son=0;
    if(!tag)//清除轻儿子贡献
    {
        modify(u,f,-1);
        idx=MAX=0;
    }
}

int main()
{
    scanf("%d",&n);
    int u,v;
    for(int i=1;i<n;i++)
    {
        scanf("%d %d",&u,&v);
        addedge(u,v),addedge(v,u);
    }
    dfs1(1,0,0);
    dfs2(1,0,0);
    for(int i=1;i<=n;i++)
        printf("%d\n",ans[i]-deep[i]);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值