洛谷上面的题解写的真的不太好,有很多错误,我来谈谈自己的理解。

设 \(f[i]\) 表示以 \(i\) 为根节点的子树中(包括节点 \(i\))的所有人安装好游戏所需要的时间(与下面的 \(g[i]\) 并没有包含关系,管理员也没有强制性要求要回到根节点,比如会出现下图情况)。

设 \(g[i]\) 表示从 \(i\) 开始往下走,兜一圈又回到 \(i\) 所需要的时间。

实际上 \(f[i]\) 可能 \(< g[i]\),比如当出现如下情况的时候:

假设下图中所有人的安装时间为 \(1\),

那么当管理员兜了一个圈,第二次到达 \(3\) 的时候,

所有人都已经安装完成了。

所以在此图中 \(f[1] < g[1]\)。

那我们先访问那个节点呢?

分为两种情况考虑,即 \(f[i] - g[i] \geq 0\) 和 \(f[i] - g[i] < 0\) 两种情况。

如果管理员回到了起点那些人还没有装完(即 \(f[i] - g[i] \geq 0\)),那么就需要等待 \(f[i] - g[i]\) 的时间所有人才能安装好。

根据常识,在等待的这段时间我们可以去下一家,以减少所需的总时间。

这里我们利用贪心,让需要等待时间最久的作为第一个访问的节点,

这样可以管理员在他漫长的安装时间内将电脑送给其他人。

而如果出现了像上图一样的情况(即 \(f[i] - g[i] < 0\)) 的情况,

根本就不需要等待,

也就不用排序,

随机访问即可,

但为了简单起见,

排了序也没有什么问题。

所以我们可以对 \(f[i] - g[i]\) 从大到小进行排序。

再挨个访问即可。

然后就是利用 \(f\) 和 \(g\) 来用子树信息更新父亲节点。

如下图:

先说结论:只安装到 \(i\) 点会需要 \(\sum (g[j] + 2) + 1 + f[i]\) 的时间能完成安装,其中 \(j\) 为比 \(i\) 先遍历到的同一层的节点(如上图)。

为什么是这样呢?

第一部分的 \(\sum (g[j] + 2)\) 表示遍历完所有 \(j\) 子树的节点,每次都回到根节点(所以要 \(+2\))。

第二部分的 \(+1\) 表示从根节点走到 \(i\) 所需要的步骤(即为 \(1\) 步)。

最后一部分的 \(f[i]\) 表示把 \(i\) 子树内所有的游戏装好了需要花的时间。

总时间取 \(\max\) 即可, 即 \(f[root] = \max\{\sum (g[j] + 2) + f[i] + 1\}\)。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector> using namespace std; const int N = 500010; struct Edge {
int to, next;
}e[N * 2]; int head[N], idx; void add(int a, int b) {
idx++;
e[idx].to = b;
e[idx].next = head[a];
head[a] = idx;
} int n, t[N];
int f[N], g[N]; void dfs(int u, int fa) {
vector<int> wait;
for (int i = head[u]; i; i = e[i].next) {
int to = e[i].to;
if (to == fa) continue;
dfs(to, u);
wait.push_back(to);
}
sort(wait.begin(), wait.end(), [](const int& a, const int& b) { return f[a] - g[a] > f[b] - g[b]; });
for (int i = 0; i < wait.size(); i++) {
f[u] = max(f[u], g[u] + 1 + f[wait[i]]);
g[u] += g[wait[i]] + 2;
}
if (t[u] > g[u] && u != 1) f[u] = max(f[u], t[u]);
} int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr); cin >> n;
for (int i = 1; i <= n; i++) cin >> t[i];
for (int i = 1; i < n; i++) {
int a, b;
cin >> a >> b;
add(a, b);
add(b, a);
}
dfs(1, 0);
cout << max(f[1], g[1] + t[1]) << '\n';
return 0;
}

P3574 [POI2014] FAR-FarmCraft 吐槽 + 题解的更多相关文章

  1. 洛谷 P3574 [POI2014]FAR-FarmCraft

    题目传送门 题目描述 输入输出格式 输入格式: 输出格式: 一行,包含一个整数,代表题目中所说的最小时间. 输入输出样例 样例输入 样例输出 提示 分析 我们设f[x]为遍历完以x为根的子树且将这棵子 ...

  2. 题解【洛谷P3574】[POI2014]FAR-FarmCraft

    题面 简化版题意: 有一棵 \(n\) 个点的树,有边权. 你初始在 \(1\) 号节点,你需要走遍整棵树为 \(2 \sim n\) 号点的居民分发电脑,但你的汽油只够经过每条边恰好两次. 一个居民 ...

  3. POI2014题解

    POI2014题解 [BZOJ3521][Poi2014]Salad Bar 把p当作\(1\),把j当作\(-1\),然后做一遍前缀和. 一个合法区间\([l,r]\)要满足条件就需要满足所有前缀和 ...

  4. 【BZOJ3829】[Poi2014]FarmCraft 树形DP(贪心)

    [BZOJ3829][Poi2014]FarmCraft Description In a village called Byteville, there are   houses connected ...

  5. [补档][Poi2014]FarmCraft

    [Poi2014]FarmCraft 题目 mhy住在一棵有n个点的树的1号结点上,每个结点上都有一个妹子. mhy从自己家出发,去给每一个妹子都送一台电脑,每个妹子拿到电脑后就会开始安装zhx牌杀毒 ...

  6. FarmCraft[POI2014]

    题目描述 In a village called Byteville, there are   houses connected with N-1 roads. For each pair of ho ...

  7. [BZOJ 3829][POI2014] FarmCraft

    先贴一波题面... 3829: [Poi2014]FarmCraft Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 421  Solved: 197[ ...

  8. 【bzoj3829】[Poi2014]FarmCraft 贪心

    原文地址:http://www.cnblogs.com/GXZlegend/p/6826667.html 题目描述 In a village called Byteville, there are   ...

  9. P3574 FAR-FarmCraft 题解

    题目 In a village called Byteville, there are \(n\) houses connected with \(n-1\) roads. For each pair ...

  10. 题解-POI2014 Supercomputer

    Problem 辣鸡bzoj权限题,洛谷链接 题意概要:一棵 \(n\) 个点有根树.\(Q\) 次询问给出一个 \(K\),回答遍历完整棵树所需最少操作次数.每次操作可以选择访问不超过 \(K\) ...

随机推荐

  1. Message源码分析

    Message 在Android中主要是在 消息循环机制 中使用,即配合 Handler,Looper和MessageQueue来进行线程切换,线程间传递数据.Message存储了我们所有需要的东西. ...

  2. 使用laravel开发微信公众的一个大坑,适合新手学习的laravel接入微信接口

    最近使用laravel做微信公众号二次开发,发现网上能够参考的资料基本上很少,很多地方都讲的不够详细,致使许多新手采坑无数,所以这篇文章讲一下如何使用laravel接入微信接口,实现微信公众号二次开发 ...

  3. Linux shell和环境变量

    环境变量 存储有关shell会话和工作环境信息:允许在内存中存储数据. 注意什么时候要用$ 什么时候不用$:用到变量,需要$;操作变量,不需要$.printenv除外 分为两类: 全局变量:对shel ...

  4. 《流畅的Python》第二版上市了,值得入手么?

    <Fluent Python>第一版在 2015 年出版,简体中文版<流畅的Python>在 2017 年出版.从那时起,它就成为了所有 Python 程序员的必读之书.如果一 ...

  5. 手记系列之四 ----- 关于使用MySql的经验

    前言 本篇文章主要介绍的关于本人在使用MySql记录笔记的一些使用方法和经验,温馨提示,本文有点长,约1.5w字,几十张图片,建议收藏查看. 一.MySql安装 下载地址:https://dev.my ...

  6. SaaS化开源项目之HouseKeeper云上部署实践

    摘要:华为云DTSE技术专家从源码构建.应用部署到系统调测,详细解读云原生SaaS应用构建的全过程. 本文分享自华为云社区<HouseKeeper云上部署实践>,作者:华为云DTSE. H ...

  7. 基于ORB-SLAM3库搭建SLAM系统

    参考资料 ORB-SLAM3配置及安装教程 ORB-SLAM3配置安装及运行 环境配置 Win 11pro VMware 17Pro Ubuntu 18.04 Eigen3 Pangolin Open ...

  8. S5PV210 | 裸机汇编LED流水灯实验

    S5PV210 | 裸机汇编LED流水灯实验 目录 S5PV210 | 裸机汇编LED流水灯实验 开发板: 1.原理图 2.Datasheet相关 3.代码 3-1.代码实现(流水灯,仅作演示) 3- ...

  9. 2023-01-14:给定一个二维数组map,代表一个餐厅,其中只有0、1两种值 map[i][j] == 0 表示(i,j)位置是空座 map[i][j] == 1 表示(i,j)位置坐了人 根据防

    2023-01-14:给定一个二维数组map,代表一个餐厅,其中只有0.1两种值 map[i][j] == 0 表示(i,j)位置是空座 map[i][j] == 1 表示(i,j)位置坐了人 根据防 ...

  10. 2020-11-15:手写代码:行有序、列也有序的二维数组中,找num,找到返回true,否则false?

    福哥答案2020-11-15: 此题来源于leetcode240和剑指 Offer(第 2 版)面试题4.1.线性查找.从二维数组的坐下角开始查找.如果当前元素等于目标值,则返回 true.如果当前元 ...