CF622E Ants in Leaves
题目大意
给定一棵 个节点的树,根节点是 。
这棵树的每一个叶节点都有一只小蚂蚁。
每过 秒钟,可以选择让一些蚂蚁向父节点走一步。
注意,两只蚂蚁不能同时在一个的节点上,除了根节点。
问这些蚂蚁最少用多少秒的时间,使得所有蚂蚁都走到根节点。
对于 的数据,保证 。
解题思路
首先将根节点分开处理。
对于根节点的每一棵子树,不能使深度相同的两个叶节点同时到达当前子树的根节点。
那么可以对于根节点的每一棵子树对每个叶子节点的深度进行排序。
显然,深度较浅的点会先到达,深度较深的点会后到达。
答案就是深度最深的点。
但是有一个问题,有深度相同的点,
所以对于深度相同的点,就强行将一些点需要的步数加 ,因为要等前面的走一步,才能走。
那么设 表示当前子树前 个叶节点的蚂蚁爬到根节点需要最少步数,
则 。
设当前子树有 个叶节点,那么答案即为所有 的最大值。
时间复杂度 。
具体见代码。
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;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18122086