CF70E Information Reform 题解

CF70E Information Reform

树形 DP 好题。一开始想成了换根,想了 2h 发现不太可做,主要是不会设计状态。套路地将节点 \(u\) 选还是不选设入状态这种方法是不可做的。

观察到 \(n\le180\),在树上问题中这个数据范围不多见,大抵是一个 \(O(n^3)\) 的算法,那么首先不管用 Floyd 还是 DFS 求出两点间距离记作 \(\text{dis}(u,v)\) 是容易的。

那么状态设计就是本题的难点,首先得到一个极为重要的引理如下。这个引理告诉我们,对于一个节点 \(u\) 所辐射的点形成一个连通块。那么既然形成了一个连通块了,就可以将问题转化为:把树分为若干个连通块,每个连通块选择一个区域信息中心的代价。

引理:设 \(t_i\) 是离节点 \(i\) 最近的区域信息中心。对于树上两点 \(u,v\),若 \(t_u=t_v=k\),则在 \(u\to v\) 路径上的所有点 \(w\) 都满足 \(t_w=k\)

那么这个问题就简单了,对于每个连通块在其根部计算贡献,设 \(f_{u,j}\) 为以 \(u\) 为根的子树中 \(t_u=j\) 的最小代价,则有

\[f_{u,j}\gets f_{u,j}+\min_{v\in\text{son}(u)}\{f_{v,k},f_{v,j}-K\} \]

实际实现中,我们只需要再记录一个使 \(f_{u,j}\) 最小的 \(j\),记作 \(g_u\),就可以把上述转移方程优化到 \(O(n^3)\)

输出方案也是容易的。

#include<bits/stdc++.h>
using namespace std;constexpr int MAXN=205;
int n,k,d[MAXN],dis[MAXN][MAXN];
vector<int>G[MAXN];
int f[MAXN][MAXN],g[MAXN],ans[MAXN];void getdis(){for(int k=1;k<=n;++k)for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
void dfs(int u,int fno){memset(f[u],0x3f,sizeof(int)*(n+5));for(int i=1;i<=n;++i) f[u][i]=d[dis[u][i]]+k;for(auto v:G[u]){if(v==fno) continue;dfs(v,u);for(int i=1;i<=n;++i)f[u][i]+=min(f[v][i]-k,f[v][g[v]]);}for(int i=1;i<=n;++i) if(f[u][i]<f[u][g[u]]) g[u]=i;
}
void dfs2(int u,int fno){for(auto v:G[u]){if(v==fno) continue;if(f[v][ans[u]]-k<f[v][g[v]]) ans[v]=ans[u];else ans[v]=g[v];dfs2(v,u);}
}int main(){cin.tie(nullptr)->sync_with_stdio(0);cin>>n>>k;for(int i=1;i<n;++i) cin>>d[i];memset(dis,0x3f,sizeof(dis));for(int i=1;i<=n;++i) dis[i][i]=0;for(int i=1,u,v;i<n;++i){cin>>u>>v;G[u].emplace_back(v);G[v].emplace_back(u);dis[u][v]=dis[v][u]=1;}getdis();dfs(1,0);cout<<f[1][g[1]]<<'\n';ans[1]=g[1];dfs2(1,0);for(int i=1;i<=n;++i) cout<<ans[i]<<" \n"[i==n];return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/881116.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读算法简史:从美索不达米亚到人工智能时代11搜索网络

20世纪70年代小型计算机普及,苹果推出Apple和Macintosh;蒂姆伯纳斯-李提出万维网,改变了网络访问方式;亚马逊采用个性化推荐算法;谷歌开发PageRank算法,引领网络搜索和关键字广告。1. 小型计算机 1.1. 到了20世纪70年代,小型计算机已在科研院所、大学和大公司中广泛应用…

Roslyn 源代码生成器 SourceGenerator 获取代码文件的本地绝对路径

本文告诉大家如何在源代码生成器 SourceGenerator 里面获取代码文件的本地文件的绝对路径从 compilation 的 Options 拿到 SourceReferenceResolver 对象,调用其 NormalizePath 方法,传入 SyntaxTree 的 FilePath 参数即可 正常项目的 SourceReferenceResolver 都是存在的,尽…

纯 CSS 来计算当前窗口的宽高

在平时我想要计算浏览器窗口的宽度高度的时候,我们会使用 resize 事件去获取,也就是 JavaScript 的方式去获取窗口的宽度高度。 今天给大家分享一个使用纯 CSS 就能计算窗口宽度高度的方法定义自定义属性: 使用@property规则来定义--vw和--vh作为自定义的CSS属性。这些属性…

宏定义

宏定义 # 和 ## #号(将符号转为字符串) 这条定义中,定义了一个 PRINT 的宏函数预处理器遇到这样的宏,会将 #a 替换成以字符串表示的参数 a 例如:##号(连接符:将2个表达式连接到一起)预处理器会将这2条宏扩展成下面的代码我们可以看到:这2条宏定义其实就是定义了2个成员…

《Operating System Concepts》阅读笔记:p2-p8

《Operating System Concepts》学习第 2 天,p2-p8 总结,总计 7 页。 一、技术总结 1.operating system An operating system is software that manages a computer’s hardware。 2.system bus data bus, address bus, control bus 统称为 system bus。 二、英语总结(生词:…

踩坑---中断中调用系统定时器延时卡死

踩坑---中断中调用系统定时器延时卡死 背景 ​ 配置外部中断作为按键输入时,调用了系统滴答定时器为基准的延时。然后每次一按按键,单片机就卡死。一开始怀疑时中断没有配置好。反复研究中断配置是否出现错误,最后debug出来,发现卡在了// 3. 等待计数值变为0,判断CTRL标志…

windows 10 安装 wsl

在 windows 上安装 Debian 版本的 wsl以管理员身份运行 cmd,执行 wsl --help 可查看 wsl 的帮助信息。执行 wsl --list --online 查看可供安装的 wsl子系统 版本。执行 wsl --install --distribution Debian 安装 debian 版本的 wsl有了计划记得推动,不要原地踏步。

开学作业13

学习使用了vue中watch知识 可以实时更新数据 也非常好用

开学作业14

前几天也是这样通过打电话合作 前后端分着写 已经完成大部分前后端的交并 预计明天写完

做开学作业10

使用的是element ui vue2 springboot技术

手把手教你如何用飞书实现betterGI消息推送

在平时,我们一般会使用betterGI的一条龙系统来完成体力的刷取,有的人可能需要知道啥时候刷完体力方便远程关闭电脑啥的,这里给大家如何通过飞书实现BetterGI消息推送的方法 1、支持的事件提醒 事件列表 notify.test : 测试通知 domain.reward : 自动秘境奖励 domain.start :…

2025【重庆联通】活动

2025年2月8日更新 扫码显示详情及办理 扫码显示详情及办理 套餐资费和活动内容均来源于重庆联通【10010人工客服可查,中国联通app官方客服可查】 这里是下面的54个活动的办理名称,请确认【点击也可直接跳转到相应位置】1.云创安全组合包10元(CQ)-立即生效 2.云创数字人名片权…