zoukankan      html  css  js  c++  java
  • UVA-12186 Another Crisis 树形dp

    题目链接:https://cn.vjudge.net/problem/UVA-12186

    题意

    给出n, T和一棵树,树上每个节点需要选择T%个直属子节点。
    问根节点一共需要选择几个节点。

    思路

    思路很明显,直接写了。

    [dp[i]=sum_{j in Child(i)} minsort(dp[j]).head( lceil kT/100 ceil ) ]

    需要非常注意的一点是复杂度问题。
    发现还挺复杂,我们假设每个节点有k个直属子节点。
    对于根节点,排序是这样的复杂度O(nlogn);
    对第一个子节点,复杂度是这样O( nlog(n/k) );
    那么最终的复杂度居然是O(nlog(n!)/k^h)?(其中h是树的层数)
    差不多是O(nlog(n-1)!)?嗯?
    等等,明天再分析这个吧,肯定不对啊。

    提交过程

    AC

    代码

    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int maxn=1e5+20;
    vector<int> stuff[maxn];
    int n, T, tmp;
    int dp(int x){
        if (stuff[x].size()==0) return 1;
    
        int len=stuff[x].size(), ans=0, size=(len*T-1)/100+1;    // upper divide
        vector<int> tmp;
        for (int i=0; i<len; i++)
            tmp.push_back(dp(stuff[x][i]));
        sort(tmp.begin(), tmp.end());
    
        for (int i=0; i<size; i++)
            ans+=tmp[i];
        return ans;
    }
    
    int main(void){
        while (scanf("%d%d", &n, &T)==2 && n){
            for (int i=0; i<maxn; i++)
                stuff[i].clear();
            for (int i=1; i<=n; i++){
                scanf("%d", &tmp);
                stuff[tmp].push_back(i);
            }
    
            printf("%d
    ", dp(0));
        }
    
        return 0;
    }
    
    
    Time Memory Length Lang Submitted
    110ms None 779 C++ 5.3.0 2018-08-08 08:32:12
  • 相关阅读:
    Vim插件:Unite新手指导(译)
    Java并发编程实战3章
    Centos6.*下安装gcc-4.8.2
    iostat详解
    国内速度比较快的NTP Server
    ssh免密登录配置
    解决卸载移动硬盘问题:umount:/usb1/:device is busy
    Centos查看系统安装日期
    主机IP规划__rsync__inotify
    熟悉OSI七层模型
  • 原文地址:https://www.cnblogs.com/tanglizi/p/9445795.html
Copyright © 2011-2022 走看看