CF622E Ants in Leaves

题目大意

给定一棵 n n n 个节点的树,根节点是 1 1 1

这棵树的每一个叶节点都有一只小蚂蚁。

每过 1 1 1 秒钟,可以选择让一些蚂蚁向父节点走一步。

注意,两只蚂蚁不能同时在一个的节点上,除了根节点。

问这些蚂蚁最少用多少秒的时间,使得所有蚂蚁都走到根节点。

对于 100 % 100\% 100% 的数据,保证 2 ≤ n ≤ 5 ∗ 1 0 5 2 \leq n \leq 5*10^5 2n5105

解题思路

首先将根节点分开处理。

对于根节点的每一棵子树,不能使深度相同的两个叶节点同时到达当前子树的根节点。

那么可以对于根节点的每一棵子树对每个叶子节点的深度进行排序。

显然,深度较浅的点会先到达,深度较深的点会后到达。

答案就是深度最深的点。

但是有一个问题,有深度相同的点,

所以对于深度相同的点,就强行将一些点需要的步数加 1 1 1,因为要等前面的走一步,才能走。

那么设 f i f_i fi 表示当前子树前 i i i 个叶节点的蚂蚁爬到根节点需要最少步数,

f i = max ⁡ ( f i , f i − 1 + 1 ) f_i=\max( f_i , f_{i-1}+1 ) fi=max(fi,fi1+1)

设当前子树有 p p p 个叶节点,那么答案即为所有 f p f_p fp 的最大值。

时间复杂度 O ( n log ⁡ n ) \mathcal O(n \log n) O(nlogn)

具体见代码。

CODE

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll read()
{
    ll a = 0, b = getchar(), c = 1;
    while (!isdigit(b))
        c = b == '-' ? -1 : 1, b = getchar();
    while (isdigit(b))
        a = a * 10 + b - '0', b = getchar();
    return a * c;
}

const int _ = 5e5 + 7;

int tot, head[_], to[_ << 1], nxt[_ << 1];

int n, ans, dp[_], now;

void add(int u, int v)
{
    to[++tot] = v;
    nxt[tot] = head[u];
    head[u] = tot;
}

void dfs(int u, int fa, int d)
{
    bool flag = 0;
    for (int i = head[u]; i; i = nxt[i])
    {
        if (to[i] != fa)
        {
            flag = 1;
            dfs(to[i], u, d + 1);
        }
    }
    if (!flag)
        dp[++now] = d;
}
void DP()
{
    for (int i = head[1]; i; i = nxt[i])
    {
        now = 0;
        dfs(to[i], 1, 1);
        sort(dp + 1, dp + now + 1);
        for (int i = 1; i <= now; ++i)
            dp[i] = max(dp[i], dp[i - 1] + 1);
        ans = max(ans, dp[now]);
    }
}

signed main()
{
    n = read();
    for (int i = 1; i < n; i++)
    {
        int x = read(), y = read();
        add(x, y), add(y, x);
    }
    DP();
    printf("%d\n", ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值