描述
题解
这个题和这一段时间的那个拉钩测评选择的最后一道题极其相似,那个题好像叫做监狱逃离,是一个七级算法,但是和这个题几乎是一样的,同样都是树,也都是树归,找一个结点作为根后开始深入,一直深入到最深层也就是说叶子结点后,开始回朔的过程中,不断进行状态的迁移,这里需要注意的是,两个题都是要考虑到同级子树的相互影响关系,这里的同级子树指得是根的父亲是同一个结点的多棵子树……这里我写的代码思路和标程略微差别,表示的是这个子树中离根最远的距离有多远,当根的距离大于等于 K 时,我们就在这个部位放置一个家丁,此时,将这个结点的状态置为 -K,因为我们知道每个家丁都可以控制 K 的范围,所以他还能向上控制 K 个,这里我们用负数表示,和标程恰好相反……具体代码不难理解,子树之间的作用关系和标程是相似的,没毛病~~~
代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
int N, K;
int ans;
int cnt = 0;
int dg[MAXN]; // 度
int dp[MAXN];
vector<int> vi[MAXN];
void dfs(int x, int pre)
{
int max_ = -INF;
int min_ = INF;
for (int i = 0; i < vi[x].size(); i++)
{
if (vi[x][i] != pre)
{
dfs(vi[x][i], x);
max_ = max(max_, dp[vi[x][i]]);
min_ = min(min_, dp[vi[x][i]]);
}
}
if (max_ == -INF)
{
max_ = min_ = 0;
}
if (max_ >= K)
{
ans++;
dp[x] = -K;
}
else if (min_ < 0 && min_ + max_ < 0)
{
dp[x] = min_ + 1;
}
else
{
dp[x] = max_ + 1;
}
}
int main()
{
// freopen("/Users/zyj/Desktop/input.txt", "r", stdin);
cin >> N >> K;
int x, y;
for (int i = 1; i < N; i++)
{
scanf("%d%d", &x, &y);
vi[x].push_back(y);
vi[y].push_back(x);
dg[x]++;
dg[y]++;
}
dfs(0, -1);
if (dp[0] > 0)
{
ans++;
}
printf("%d\n", ans);
return 0;
}