[POI2014]FAR-FarmCraft (树规+贪心)
题干
In a village called Byteville, there are houses connected with N-1 roads. For each pair of houses, there is a unique way to get from one to another. The houses are numbered from 1 to . The house no. 1 belongs to the village administrator Byteasar. As part of enabling modern technologies for rural areas framework, computers have been delivered to Byteasar's house. Every house is to be supplied with a computer, and it is Byteasar's task to distribute them. The citizens of Byteville have already agreed to play the most recent version of FarmCraft (the game) as soon as they have their computers. Byteasar has loaded all the computers on his pickup truck and is about to set out to deliver the goods. He has just the right amount of gasoline to drive each road twice. In each house, Byteasar leaves one computer, and immediately continues on his route. In each house, as soon as house dwellers get their computer, they turn it on and install FarmCraft. The time it takes to install and set up the game very much depends on one's tech savviness, which is fortunately known for each household. After he delivers all the computers, Byteasar will come back to his house and install the game on his computer. The travel time along each road linking two houses is exactly 1 minute, and (due to citizens' eagerness to play) the time to unload a computer is negligible. Help Byteasar in determining a delivery order that allows all Byteville's citizens (including Byteasar) to start playing together as soon as possible. In other words, find an order that minimizes the time when everyone has FarmCraft installed.
INPUT
OUTPUT
The first and only line of the standard output should contain a single integer: the (minimum) number of minutes after which all citizens will be able to play FarmCraft together.
奇妙的翻译
mhy住在一棵有n个点的树的1号结点上,每个结点上都有一个妹子。
mhy从自己家出发,去给每一个妹子都送一台电脑,每个妹子拿到电脑后就会开始安装zhx牌杀毒软件,第i个妹子安装时间为。
树上的每条边mhy能且仅能走两次,每次耗费1单位时间。mhy送完所有电脑后会回自己家里然后开始装zhx牌杀毒软件。
卸货和装电脑是不需要时间的。
求所有妹子和mhy都装好zhx牌杀毒软件的最短时间。
(哪里冒出来的妹子???)
瞎想:
- 每条边都只能走两次,而且我们最后必须回到老家,意味着我们必须一次遍历完整棵树(包括每棵子树)
- 读完题我们要get到一个很重要的点:装软件和送电脑是可以同时进行的(妹子居然会装电脑! )
- 我们假设一个节点有两个子节点A和B,定义 f[i] 为遍历完子树后再回到 i 点的最短用时,siz[i] 为 i 的子树的总大小,那么,我们可以得到:
- 先去遍历A的子树,总时间:siz[A]*2 + f[B] ;//当然这里其实是要+1的,因为我们从A或B到 i 还需要再走一步,看我下面代码可以知道,这里不影响
- 先去遍历B的子树,总时间:siz[B]*2 + f[A] ;
- 我们用结构体记录下所有子树的( f[i] , siz[i]*2)
- 按照 time +p.siz < p.time + siz 从小到大排序
- 理由:如果先遍历A更合适,有 siz[A]2+f[B] < siz[B]2+f[A]; //这里之前脑子一抽写反了,希望没误导大家...
- 这里我觉得解释一下比较好,相比较而言,我们肯定更愿意先去安装软件耗时更多而跑图用时更少的子树,因为这样我们就可以让他们在我们给别的地方送电脑的时候自行安装,从而节省时间。那么在这里,我们假设f[A]和f[B]相等,那么此时siz[B]肯定是大于siz[A]的,这意味这A和B的总用时相等,但我们遍历B时耽搁在路上的时间更多(子树规模更大嘛),所以相比较而言A的装软件用时更长,也就是我们应该先走A;
- 最后的答案 f[x]=max(w[x],f[v]+sum)
这里我们结合代码分析一下:
struct node{
int time,siz;
bool operator <(const node& p)const{
return p.time+siz<time+p.siz;
}
}t[maxn];
void dfs(int u,int fa){
siz[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
}
int tot=0;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa) continue;
tot++;//儿子数量
t[tot].time=f[v]+1;//从v回到u需加1
t[tot].siz=siz[v]*2;//这里乘2,下面计算时就不用乘2了,减少失误
}
sort(t+1,t+1+tot);
int sum=0,maxx=(siz[u]-1)*2;//sum依然是目前跑路所需总时间,maxx初始为单纯跑完u的子树所需总时间
for(int i=1;i<=tot;i++){
maxx=max(maxx,t[i].time+sum);//更新目前最大用时
sum+=t[i].siz;//累加跑路时间
}
f[u]=max(w[u],maxx);//如果单单u点装软件用时比完全弄完所有子树都费事,直接取w[u]
}
完整代码如下:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=5*1e6+10;
int n,f[maxn],head[maxn],len=0,siz[maxn];
int w[maxn];
struct Edge{
int next,to;
}edge[maxn<<1];
void Add(int u,int v){
edge[++len].next=head[u];
edge[len].to=v;
head[u]=len;
}
struct node{
int time,siz;
bool operator <(const node& p)const{
return p.time+siz<time+p.siz;
}
}t[maxn];
void dfs(int u,int fa){
siz[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
}
int tot=0;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa) continue;
tot++;
t[tot].time=f[v]+1;
t[tot].siz=siz[v]*2;
}
sort(t+1,t+1+tot);
for(int i=1;i<=tot;i++)
printf("%d %d\n",t[i].time,t[i].siz);
int sum=0,maxx=(siz[u]-1)*2;
for(int i=1;i<=tot;i++){
maxx=max(maxx,t[i].time+sum);
sum+=t[i].siz;
}
f[u]=max(w[u],maxx);
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
Add(u,v),Add(v,u);
}
dfs(1,0);
int ans=0;
ans=max(f[1],w[1]+(n-1)*2);
cout<<ans<<endl;
return 0;
}
[POI2014]FAR-FarmCraft (树规+贪心)的更多相关文章
- [HEOI2015]兔子与樱花 树规+贪心
鬼能想到是个贪心.明明觉得是树规啊..又完美爆零.. 从叶子节点往上更新,能保证最优解(这块想了半天). 证明:当你的子树上有能删的点而你不删时,可能会对子树的根节点有利,最好的情况是使子树根节点由不 ...
- [Poi2014]FarmCraft 树状dp
对于每个点,处理出走完其子树所需要的时间和其子树完全下载完软件的时间 易证,对于每个点的所有子节点,一定优先选择差值大的来给后面的时间 树规+贪心. #include<cstdio> #i ...
- Codeforces Gym 100231B Intervals 线段树+二分+贪心
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...
- BZOJ_3524_[Poi2014]Couriers_主席树
BZOJ_3524_[Poi2014]Couriers_主席树 题意:给一个长度为n的序列a.1≤a[i]≤n. m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r- ...
- 【BZOJ5495】[十二省联考2019]异或粽子(主席树,贪心)
[BZOJ5495][十二省联考2019]异或粽子(主席树,贪心) 题面 BZOJ 洛谷 题解 这不是送分题吗... 转异或前缀和,构建可持久化\(Trie\). 然后拿一个堆维护每次的最大值,每次如 ...
- 【arc073e】Ball Coloring(线段树,贪心)
[arc073e]Ball Coloring(线段树,贪心) 题面 AtCoder 洛谷 题解 大型翻车现场,菊队完美压中男神的模拟题 首先钦定全局最小值为红色,剩下的袋子按照其中较大值排序. 枚举前 ...
- 【9.2校内测试】【开学祭】【exgcd】【树规(背包】【模拟】
比较裸的$exgcd$的应用? $exgcd$可以算出在$x$和$y$分别是最小正整数时的解.注意在这里因为有$a(x+\frac{b}{d})+b(y-\frac{a}{d})=c$,$d=gcd( ...
- 【agc028E】High Elements(动态规划,线段树,贪心)
[agc028E]High Elements(动态规划,线段树,贪心) 题面 AtCoder 你有一个\([1,N]\)的排列\(P\). 一个长度为\(N\)的字符串\(S\)是好的,当且仅当: 两 ...
- BZOJ3829[Poi2014]FarmCraft——树形DP+贪心
题目描述 In a village called Byteville, there are houses connected with N-1 roads. For each pair of ho ...
随机推荐
- 一篇文章快速入门React框架
视频教程 本文章在B站配有视频教程 课程目标 了解最常用的React概念和相关术语,例如JSX,组件,属性(Props),状态(state). 构建一个非常简单的React应用程序,以阐述上述概念. ...
- lambda表达式操作DataTable
using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Text; ...
- 异步函数async await在wpf都做了什么?
首先我们来看一段控制台应用代码: class Program { static async Task Main(string[] args) { System.Console.WriteLine($& ...
- virtualbox 基于nat模式搭建局域网并且和宿主机通信
1.VIRTUALbox 2.两台虚拟机,设置网络为DHCP方式 检查文件确认是dhcp模式不是的百度搜索修改:/etc/sysconfig/network-scripts/ifcfg-enps3(网 ...
- [NOI Online #3]魔法值
题目 点这里看题目. 分析 我们不难想到,对于系数进行一下的拆分: \[\begin{aligned} f(u,j)&=\bigoplus_{(u,v)\in E} f(v,j-1)\ ...
- Java——几点重要知识笔记(一)
学了Java有一段时间了,自认为有一些基础知识比较重要,因此记下来共享,不喜勿喷. 一.标识符 (1)定义:在Java语言中,凡是对类,方法,变量,包,参数等命名时,所使用的字符序列 (2)包含的内容 ...
- 使用Apache Spark和Apache Hudi构建分析数据湖
1. 引入 大多数现代数据湖都是基于某种分布式文件系统(DFS),如HDFS或基于云的存储,如AWS S3构建的.遵循的基本原则之一是文件的"一次写入多次读取"访问模型.这对于处理 ...
- 如何安装vim自动补全插件YouCompleteMe(YCM)
Vim是全平台上一个高度可拓展的编辑器.它本身只是一个简陋的编辑器,但是因为有各种插件而变得强大.使用Vim编写代码就不免遇到代码补全的问题.常用的代码补全插件有两个:日本人shougo写的neoco ...
- Appium查看应用包名
方式一没有apk 如果应用已经安装在手机上了(例如应用商城下载).可以直接打开手机上该应用, 进入到要操作的界面然后执行: adb shell dumpsys activity recents | f ...
- Ubuntu搭建Java开发环境-刘志敏-专题视频课程
Ubuntu搭建Java开发环境-3人已学习 课程介绍 主要介绍在Ubuntu环境如何安装Java开发的基本环境课程收益 学会Ubuntu中安装jdk.mysql.maven和id ...