P3574 [POI2014] FAR-FarmCraft 题解

题目需要我们从一号节点开始遍历整棵树,并给每一个节点记录下遍历到其的时间。
同时每一个节点又有一个自己的倒计时,当遍历到其的时候就开始计时。
我们需要求出所有节点中倒计时结束最慢的那一个的结束时间,并最小化之。

我们不难想象出一个简单的DP式子来求得最终的答案:

对于节点 u 的子树 v,我们有如下的DP式子:

dp[u]=max(dp[u],dp[v]+sz[u]+1)

其中 dp[u] 代表当前子树中最大的答案;
sz[u] 代表遍历过 v 所在的子树之前已经经过的所有子树的大小之和再乘以2,这个在遍历完毕整个子树之后会更新为该子树的大小乘以2。

我们可以发现,我们最终的答案跟遍历子树的顺序有关,于是我们考虑对其进行排序。

对于一个节点 x 的两个子树 yz,我们假设先遍历 y 再遍历 z
这样的话,我们的答案就是 max(dp[y]+sz[u]+1,dp[z]+sz[u]+sz[y]+2+1)
我们假定这个方案比交换两个子树的遍历顺序得到的答案更优。
交换两个子树的遍历顺序之后得到的答案就是 max(dp[z]+sz[u]+1,dp[y]+sz[u]+sz[z]+2+1)

我们最终得到如下式子:

max(dp[y]+sz[u]+1,dp[z]+sz[u]+sz[y]+2+1)>max(dp[z]+sz[u]+1,dp[y]+sz[u]+sz[z]+2+1)

我们将不等式左右两边同时约掉 sz[u]+1,得到

max(dp[y],dp[z]+sz[y]+2)>max(dp[z],dp[y]+sz[z]+2)

因为 dp[y]<dp[y]+sz[z]+2dp[z]<dp[z]+sz[y]+2,所以一定是 dp[y]+sz[z]+2dp[z]+sz[y]+2 之间的差值导致了答案的变化。

因此,我们可以得到

dp[y]sz[y]<dp[z]sz[z]

然后我们就可以按照这样的方法排序了。

参考代码如下:

#include<bits/stdc++.h> using namespace std; #define ll long long const int N = 500010; template<typename T> inline T read() { T x = 0, f = 1; char c = getchar(); while(!isdigit(c)) { if(c == '-')f = -1; c = getchar(); } while(isdigit(c))x = x * 10 + (c ^ 48), c = getchar(); return x * f; } int n; vector<int>e[N]; int val[N]; int f[N], sz[N]; bool cmp(const int a, const int b) { return sz[a] - f[a] < sz[b] - f[b]; } void dfs(int p, int fa) { if(p != 1)f[p] = val[p]; if(e[p].empty())return; for(auto i : e[p]) if(i != fa)dfs(i, p); sort(e[p].begin(), e[p].end(), cmp); for(auto i : e[p]) { if(i == fa)continue; f[p] = max(f[p], f[i] + sz[p] + 1); sz[p] += sz[i] + 2; } } int main() { n = read<int>(); for(int i = 1; i <= n; i++) val[i] = read<int>(); for(int i = 1; i < n; i++) { int u = read<int>(), v = read<int>(); e[u].push_back(v); e[v].push_back(u); } dfs(1, 0); printf("%d\n", max(f[1], sz[1] + val[1])); return 0; }

__EOF__

本文作者Kaiser Wilheim
本文链接https://www.cnblogs.com/kaiserwilheim/p/16481902.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   南陽劉子驥  阅读(36)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示