【动态规划】【贪心】 [POI2011] DYN-Dynamite
这俩东西是怎么结合到一起的?
题目描述
给一棵树,树上有一些关键节点,要求你选
算法描述
让最大值最小,二分答案判断可行性。假设现在
但是,存在一种从子树中心选的点覆盖这个
我们考虑几种需要修改
-
,这时如果再拖延就没有办法覆盖到这个距离为 的点了,所以 ,在 处设关键点。 -
,这时可以用子树中的 直接覆盖 ,所以 。 -
,这个点是关键点,且无法被子树中的点覆盖,所以需要记录这个关键点为 “未覆盖的点”, 。
然后二分答案时判断
时间复杂度
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 5,inf = 0x3f3f3f3f;
int f[N],g[N],n,m,cnt = 0,mid,d[N];
vector <int> G[N];
inline void dp(int x,int last)
{
f[x] = -inf; g[x] = inf;
for(auto to : G[x])
{
if(to == last) continue;
dp(to,x);
f[x] = max(f[x],f[to] + 1);
g[x] = min(g[x],g[to] + 1);
}
if(f[x] + g[x] <= mid) f[x] = -inf;
if(g[x] > mid && d[x] == 1) f[x] = max(f[x],0);
if(f[x] == mid) ++cnt,f[x] = -inf,g[x] = 0;
}
inline bool check()
{
cnt = 0;
dp(1,0);
if(f[1] >= 0) cnt++;
return cnt <= m;
}
int main()
{
ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i = 1;i <= n;i++) cin>>d[i];
for(int i = 1,x,y;i <= n - 1;i++)
{
cin>>x>>y;
G[x].push_back(y);
G[y].push_back(x);
}
int l = 0,r = n;
while(l < r)
{
mid = (l + r) >> 1;
if(check()) r = mid;
else l = mid + 1;
}
cout<<l;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现