• 洛谷P3574 [Poi2014]FarmCraft 树形DP


    题目描述

    (英语版)

      In a village called Byteville, there are nn houses connected with n-1n1 roads.

    For each pair of houses, there is a unique way to get from one to another.

    The houses are numbered from 1 to nn.

    The house no. 1 belongs to the village administrator Byteasar.

    As part of enabling modern technologies for rural areas framework, nn 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.

    (洛谷中文版)

      在一个叫做比特村的小村庄中,有n-1n1条路连接着这个村庄中的全部nn个房子。

    每两个房子之间都有一条唯一的通路。这些房子的编号为1至nn。

    1号房子属于村庄的管理员比特安萨尔。

    为了提升村庄的科技使用水平,nn台电脑被快递到了比特安萨尔的房子。每个房子都应该有一台电脑,且分发电脑的任务就落在了比特安萨尔的肩上。

    比特村的居民一致同意去玩农场物语这个游戏的最新快照版,而且好消息是他们很快就要得到他们最新的高配置电脑了。

    比特安萨尔将所有电脑都装在了他的卡车上,而且他准备好完成这个艰巨的任务了。

    他的汽油恰好够走每条路两遍。

    在每个房子边,比特安萨尔把电脑贴心的配送给居民,且立即前往下一个房子。(配送过程不花费任何时间)

    只要每间房子的居民拿到了他们的新电脑,它们就会立即开始安装农场物语。安装农场物语所用的时间根据居民的科技素养而定。幸运的是,每间房子中居民的科技素养都是已知的。

    在比特安萨尔配送完所有电脑后,他会回到他自己的1号房子去安装他自己的农场物语。

    用卡车开过每条路的时间恰好是1分钟,而居民开电脑箱的时间可以忽略不计。(因为他们太想玩农场物语了)

    请你帮助比特安萨尔算出从开始配送到所有居民都玩上了农场物语的最少时间。

    输入输出格式

    输入格式:

    第一行包含一个整数n(2n500000),代表比特村中有多少房子。

    第二行包含nn个整数c_1, c_2, ⋯, c_n,c1,c2,,cn(1ci109),每个数都被单个空格隔开。c_ici是第i号房间中居民安装农场物语所用的时间。

    接下来的n-1n1行代表了每一条路的两个顶点。两个顶点aa和bb满足(1a<bn),两个数之间有一个空格。

    输出格式:

    一行,包含一个整数,代表题目中所说的最小时间。

    输入输出样例

    输入

    6
    1 8 9 6 3 2
    1 3
    2 3
    3 4
    4 5
    4 6

    输出

    11

    思路分析:
      
    这道题要求我们找到最小时间,而且n个点共有n-1条边,我们就要想到树形dp。
      当我们从根节点走到节点u时,我们就要考虑在之后进入u的子节点的顺序。这就与贪心的思想有关了,由于一个节点的最终时间花销
    为到达该节点的时间与该节点所需安装时间的总和,而最终影响答案的是整个子树的每个节点的所需时间的最大值。我们想,当然是先去安
    装花费时间最长的。这样就可以在安装后续的子节点时节省一些时间,因为我们可以让安装时间长的节点在之后先行安装。
      因此我们可以对u的子节点进行排序。我们用数组size[u]来表示遍历完以u为节点的整个子树所需的时间,用f[u]表示子树中所有用
    户安装完所需的时间总和.则对于节点u,我们可以将它所有的儿子按f[u]-size[u]进行逆序排序,即按所有子树中相对安装时间最大的
    进行访问,这样就可以达到时间最小的目的.

    edge数组开小居然会MLE


    参考代码:
      
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 const int N=5e5+10;
     6 int f[N],a[N],size[N];
     7 int n;
     8 struct Node{
     9     int next,to;
    10 }edge[N*2];
    11 int Head[N],tot;
    12 void Add(int x,int y){
    13     edge[++tot].to=y;
    14     edge[tot].next=Head[x];
    15     Head[x]=tot;
    16 }
    17 bool cmp(int x,int y){ //比较函数,用于排序。 
    18     return f[x]-size[x]>f[y]-size[y];
    19 }
    20 int p[N];//储存节点u的每一个子节点. 
    21 void dfs(int u,int fa){
    22     if(u!=1) f[u]=a[u];
    23     for(int i=Head[u];i;i=edge[i].next){
    24         int v=edge[i].to;
    25         if(v==fa) continue;
    26         dfs(v,u); 
    27     }
    28     int T=0;
    29     for(int i=Head[u];i;i=edge[i].next){
    30         int v=edge[i].to;
    31         if(v==fa) continue;
    32         p[++T]=v;
    33     }
    34     sort(p+1,p+1+T,cmp);
    35     for(int i=1;i<=T;++i){
    36         f[u]=max(f[u],f[p[i]]+size[u]+1);
    37         size[u]+=size[p[i]]+2;   //由于从u到v和从v到u走了两次,所以size[u]+=size[p[i]]+2 
    38     }
    39 }
    40 int main(){
    41     scanf("%d",&n);
    42     for(int i=1;i<=n;++i)
    43         scanf("%d",&a[i]);
    44     for(int i=1;i<n;++i){
    45         int x,y;
    46         scanf("%d%d",&x,&y);
    47         Add(x,y);Add(y,x);
    48     }
    49     dfs(1,0);
    50     printf("%d
    ",max(f[1],size[1]+a[1]));//由于最后安装1号节点,拿出来进行比较. 
    51 }
    
    
    
  • 相关阅读:
    转发与重定向的区别
    Servlet开发详讲
    Servlet的常见错误
    HTTP请求方式之POST和GET的区别
    Spring各种类型数据的注入
    Spring容器的基本使用
    Python接口自动化-测试用例编写
    Python接口自动化-设计测试用例
    python简明教程之数据结构(列表、元组、字典、集合)
    python简明教程之函数
  • 原文地址:https://www.cnblogs.com/li-jia-hao/p/12650241.html
Copyright © 2020-2023  润新知