专栏文章
题解:P12659 [KOI 2023 Round 1] 加油站
P12659题解参与者 4已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @minlpy8x
- 此快照首次捕获于
- 2025/12/02 04:28 3 个月前
- 此快照最后确认于
- 2025/12/02 04:28 3 个月前
一道贪心题,本人感觉这题有绿的难度。
题意
一棵树,要求在上面标记点,使得任意一条长度为 的简单路径都至少含有一个被标记的点。求最少标记多少点。
转化一下题意,给每一个叶子节点都向外扩展出一个虚拟的被标记的点,合法方案即任意两个被标记的点,若它们之间没有其他被标记的点,则它们的简单距离不超过 。
思路
定义 表示 节点子树中, 与一个被标记的、到 简单路径中没有其他点被标记(包括本身)的点的简单路径长度的最大值。
如果一个点 ,如果它有一个子节点的 大于等于 ,或是对于它的任意两个不同的子节点 、,有 ,那么就需要标记这个点,否则不用。
贪心正确性
如果有一个点,它没有满足上述思路的标记条件,但被标记了,那么它可能会使用同样的标记数,它的祖先节点的 没有上述思路生成的小。这一定不是最优的。
代码
CPP#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
long long n,m,d[maxn],ans;
vector<int> a[maxn];
void dfs(int u,int fa)
{
int max1=0,max2=0;//最大和次大的d
for(int v:a[u])
if(v!=fa)
{
dfs(v,u);
if(d[v]>max1)
{
max2=max1;
max1=d[v];
}
else if(d[v]>max2)
max2=d[v];
}
if(max1+max2>=m)
{
ans++;
d[u]=0;
}
else
d[u]=max1+1;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
dfs(1,0);
cout<<ans;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...