zoukankan      html  css  js  c++  java
  • [补档][Poi2014]FarmCraft

    [Poi2014]FarmCraft

    题目

    mhy住在一棵有n个点的树的1号结点上,每个结点上都有一个妹子。
    mhy从自己家出发,去给每一个妹子都送一台电脑,每个妹子拿到电脑后就会开始安装zhx牌杀毒软件,第i个妹子安装时间为Ci。
    树上的每条边mhy能且仅能走两次,每次耗费1单位时间。mhy送完所有电脑后会回自己家里然后开始装zhx牌杀毒软件。
    卸货和装电脑是不需要时间的。
    求所有妹子和mhy都装好zhx牌杀毒软件的最短时间。

    INPUT

    第一行输入一个整数N,表示有N个结点
    第二行有N个整数C1,C2...Cn,Ci表示第i个妹子安装杀毒软件的时间
    接下来的N-1行,每行两个整数x,y,表示x与y之间有一条无向边

    OUTPUT

    输出文件仅包含一行,一个整数表示让所有妹子和mhy装好杀毒软件的最短时间

    SAMPLE

    INPUT

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

    OUTPUT

    11

    解题报告

    翻译真累= =,原题英文版,结果发现翻译跟英文啥关系没有,就粘了翻译,然后发现输入格式跟输出格式都没有翻译,然后= =,然后我就强行翻译了一发= =
    考试时打了个dfs,骗了5分- -
    正解:
    贪心。
    我们分析题干,发现每条边只能过两次,也就是一进一出,那么我们进了一个点,我们就要遍历完整个子树,所以我们只能跑一遍dfs,然后我们发现dfs一遍的时间是一定的,那么见每个妹子的时间就在这个时间轴上。
    我们定义一个数组rest,代表遍历完这个节店的子树,以后我们还要为这个节点所费的时间。
    1. 除了1节点,见到一个妹子杀一下毒
    2. 我们发现答案是Max(rest[1],c[1])+2×(n-1)
    3. 我们考虑如何找rest,我们发现,每个节点的最优rest是 子节点的rest,减去其在这个子树里又经过的时间 再和 它的c减去遍历它的时间 取个Max
     1 #include<algorithm>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 using namespace std;
     7 inline int read(){
     8     int sum(0);
     9     char ch(getchar());
    10     for(;ch<'0'||ch>'9';ch=getchar());
    11     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
    12     return sum;
    13 }
    14 int n;
    15 int w[500001];
    16 int fa[500001],t[500001],rest[500001];
    17 inline int my_max(int a,int b){
    18     return a>b?a:b;
    19 }
    20 inline int my_min(int a,int b){
    21     return a<b?a:b;
    22 }
    23 vector<int>g[500001];
    24 inline bool cmp(const int &a,const int &b){
    25     return rest[a]>rest[b];
    26 }
    27 inline void dfs(int u){
    28     int size(g[u].size());
    29     for(int i=0;i<size;i++){
    30         int e(g[u][i]);
    31         if(e!=fa[u]){
    32             t[u]++;
    33             fa[e]=u;
    34             dfs(e);
    35             t[u]++;
    36             t[u]+=t[e];
    37         }
    38     }
    39     if(u!=1)
    40         rest[u]=w[u]-t[u];
    41     int tmp(t[u]);
    42     sort(g[u].begin(),g[u].end(),cmp);
    43     for(int i=0;i<size;i++){
    44         int e(g[u][i]);
    45         if(e!=fa[u]){
    46             tmp-=2+t[e];
    47             rest[u]=my_max(rest[u],rest[e]-tmp-1);
    48         }
    49     }
    50     rest[u]=my_max(0,rest[u]);
    51 //  cout<<u<<' '<<w[u]<<' '<<rest[u]<<endl;
    52 }
    53 int main(){
    54     n=read();
    55     for(int i=1;i<=n;i++)
    56         w[i]=read();
    57     for(int i=1;i<n;i++){
    58         int x(read()),y(read());
    59         g[x].push_back(y),g[y].push_back(x);
    60     }
    61     dfs(1);
    62     printf("%d",my_max(rest[1],w[1])+(n<<1)-2);
    63 }
    View Code
  • 相关阅读:
    Oracle中job的使用详解
    Control File (二)重建CONTROLFILE --- NORESETLOG
    Oracle Analyze 命令 详解
    深入学习Oracle分区表及分区索引
    B树索引和位图索引的区别!
    RAID0_RAID1_RAID10_RAID5各需几块盘才可组建
    Oracle IO优化心得
    修改dbwr后台进程数量
    查看ORACLE执行计划的几种常用方法
    printf()格式化输出详解及echo带颜色输出
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7277714.html
Copyright © 2011-2022 走看看