zoukankan      html  css  js  c++  java
  • 树规+贪心 问题 B: [Poi2014]FarmCraft

    问题 B: [Poi2014]FarmCraft

    时间限制: 1 Sec  内存限制: 128 MB

    题目描述

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

    输入

    The first line of the standard input contains a single integer N(2<=N<=5 00 000)  that gives the number of houses in Byteville. The second line contains N integers C1,C2…Cn(1<=Ci<=10^9), separated by single spaces; Ci is the installation time (in minutes) for the dwellers of house no. i.
    The next N-1  lines specify the roads linking the houses. Each such line contains two positive integers a and b(1<=a<b<=N) , separated by a single space. These indicate that there is a direct road between the houses no. a and b.

    输出

    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.

    样例输入

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

    样例输出

    11
    

       

          本节的最小值一定是儿子节点的最小值,而当从一棵树上走出来时,距离整棵树安装完的时间越大,就该越先遍历。所以只需记录一下每个节点的这个值就行了(定义为rest[])。那么该如何求呢?
         先走rest最大的子树,走完这棵子树后,去走rest[]次大的子树,此时,上一个子树传下来的rest相应减少了遍历第二棵子树所用时间,所以此时rest最大值可能来自新遍历的子树rest。记录一下就好了。
          过程是先遍历子树,再模拟子树被遍历的过程。
          最后的答案就是根节点的rest+2*(n-1)【遍历整棵树所用时间】(注:因为根节点最后装,所以记得特判)
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define N 500005
    #define inf 1000000000
    using namespace std;
    ll n,a[N],adj[N],e,zong[N],xiao[N],rest[N];
    struct node
    {
        ll v,next;
    } lu[N*2];
    struct tree
    {
        ll h,sum;
    } b[N];
    inline void add(int u,int v)
    {lu[++e].v=v;lu[e].next=adj[u];adj[u]=e;}
    inline ll read()
    {
        ll sum=0,f=1;char x=getchar();
        while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
        while(x>='0'&&x<='9'){sum=sum*10+x-'0';x=getchar();}
        return sum;
    }
    ll cmp(const tree &a,const tree &b)
    {
        return a.sum>b.sum;
    }
    void dfs(int x,ll fa)
    {
        ll k=inf,sum=0,s=0;
        for(int i=adj[x];i;i=lu[i].next)
        {
            int to=lu[i].v;
            if(to!=fa)
            {
               dfs(to,x),k=0;
               xiao[x]+=xiao[to];
            }
        }
         
        if(k==inf)
        {
           xiao[x]=2;
           rest[x]=a[x]-1;
           return;
        }
         
        for(int i=adj[x];i;i=lu[i].next)
        {
            int to=lu[i].v;
            if(to==fa)continue;
            sum++;
            b[sum].h=xiao[to];
            b[sum].sum=rest[to];
        }
        sort(b+1,b+sum+1,cmp);
        s=b[1].sum;
        for(int i=2;i<=sum;i++)
            s=max(b[i].sum,s-b[i].h);
        if(x!=1)
           rest[x]=max(s,a[x]-xiao[x])-1;
        else
           rest[x]=max(a[x],s);
        if(rest[x]<0)rest[x]=0;
        xiao[x]+=2;
    }
    int main()
    {
        //freopen("farmcraft.in","r",stdin);
        //freopen("farmcraft.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++)
            a[i]=read();
        int x,y;
        for(int i=1;i<n;i++)
        {
            x=read();y=read();
            add(x,y);add(y,x);
        }
        dfs(1,0);
        cout<<2*(n-1)+rest[1];
    }

  • 相关阅读:
    leetcode Remove Linked List Elements
    leetcode Word Pattern
    leetcode Isomorphic Strings
    leetcode Valid Parentheses
    leetcode Remove Nth Node From End of List
    leetcode Contains Duplicate II
    leetcode Rectangle Area
    leetcode Length of Last Word
    leetcode Valid Sudoku
    leetcode Reverse Bits
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632756.html
Copyright © 2011-2022 走看看