P3523 POI2011 DYN-Dynamite
P3523 POI2011 DYN-Dynamite
小 trick,加双倍经验。
思路
使
那么可以把问题转化为,所有关键点到选择的点的距离小于
这就是:P3942 将军令
考虑设
这里覆盖指:对于一个关键点,到最近的被选中点的距离小于等于当前二分的
有朴素转移:
然后要分讨一下(下文中的
-
当
且 为关键点。 。解释:显而易见,当前点可以作为一个没有被覆盖的关键点。
-
当
。 。解释:显然没有一个没被覆盖的关键点,易证
和 不来自一棵子树。 -
当
。 且需选择的点个数加一。解释:该点必须被选择。
最后判断一下根的
然后套上二分就 OK 了。
CODE
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
struct Edge
{
int tot;
int head[maxn];
struct edgenode{int to,nxt;}edge[maxn*2];
inline void add(int x,int y)
{
tot++;
edge[tot].to=y;
edge[tot].nxt=head[x];
head[x]=tot;
}
}T;
int n,m;
int a[maxn];
int g[maxn],f[maxn];
int gs;
inline void dfs(int u,int fa,int mid)
{
g[u]=-1e9,f[u]=1e9;
for(int i=T.head[u];i;i=T.edge[i].nxt)
{
int v=T.edge[i].to;
if(v==fa) continue;
dfs(v,u,mid);
f[u]=min(f[v]+1,f[u]);
g[u]=max(g[v]+1,g[u]);
}
if(f[u]>mid&&a[u]) g[u]=max(g[u],0);
if(f[u]+g[u]<=mid) g[u]=-1e9;
if(g[u]==mid) f[u]=0,g[u]=-1e9,gs++;
}
inline void solve(int mid)
{
gs=0;
dfs(1,0,mid);
gs+=(g[1]>=0);
printf("%d",gs);
}
int main()
{
int t;
scanf("%d%d%d",&n,&m,&t);
for(int i=1;i<=n;i++) a[i]=1;
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
T.add(u,v),T.add(v,u);
}
solve(m);
}
分类:
动态规划/dp / 树上 dp
, trick / 树上点覆盖
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现