#include<bits/stdc++.h>
using namespace std;
long long w[100007],sum[100007];
int fa[100007],degree[100007],dp[100007],depth[100007];
int flag[100007];
int vis[100007];
int find_x(int x)//非递归并查集
{
    int k, j, r;
    r = x;
    while(r != dp[r])     //查找根节点
        r = dp[r];      //找到根节点,用r记录下
    k = x;
    while(k != r)             //非递归路径压缩操作
    {
        j = dp[k];         //用j暂存parent[k]的父节点
        dp[k] = r;        //fa[x]指向根节点
        k = j;                    //k移到父节点
    }
    return r;         //返回根节点的值
}
int main(){
    int n,l;
    long long s;
    scanf("%d%d%lld",&n,&l,&s);
    for(int i=1;i<=n;i++){
        scanf("%lld",&w[i]);
        if(w[i]>s)//这个权重超重
            return puts("-1"),0;
    }
    for(int i=2;i<=n;i++){
        scanf("%d",&fa[i]);
        degree[fa[i]]++;//双亲结点度数+1
    }
    for(int i=1;i<=n;i++){
        dp[i]=i;
        depth[i]=depth[fa[i]]+1;//深度为双亲结点深度+1
        sum[i]=sum[fa[i]]+w[i];//这一点的总权重为双亲结点总权重+自己权重
    }
    int h=0,cnt=0,ans=0;
    for(int i=1;i<=n;i++){
        if(!degree[i])//i为叶子节点
            flag[cnt++]=i;//记录叶子节点位置
    }
    while(h<cnt){
        int x=flag[h++];
        if(vis[x])
            continue;
        ans++;
        int num=0;
        long long val=0;
        while(x){
            int next=find_x(x);//第一次是自己,之后是祖先(它被合并入它的双亲)
            if(vis[next]==1)//当它变成祖先时,这个向上贪心的点已经被选中
                break;//这句去掉一样能过,多跑15ms,感觉加上比较好
            num+=depth[x]-depth[next]+1;//这一条路的节点数
            val+=sum[x]-sum[next]+w[next];////这一条路的总权重
            if(num>l||val>s)//超长或者超重就停止,无法继续贪心
                break;
            vis[next]=1;//这个节点已经被选中,所有的点都只能被选中一次
            degree[fa[next]]--;//next的双亲结点度数减一
            if(!degree[fa[next]])//如果nect的双亲结点成为叶子节点
                flag[cnt++]=fa[next];//记录它的位置
            dp[next]=find_x(fa[dp[next]]);//把这个点并到它父亲里
            x=fa[next];//贪心它的父亲
        }
    }
    printf("%d\n",ans);
    return 0;
}
/*while(h<t)
    {
        int x=q[h++];
        if(vis[x]) continue;
        ++Ans;
        int num=0; LL s=0;
        while(x)
        {
            int nxt=Find(x);
            num+=depth[x]-depth[nxt]+1, s+=sum[x]-sum[nxt]+w[nxt];
            if(num>L||s>S) break;
            vis[nxt]=1;
            if(!--dgr[fa[nxt]]) q[t++]=fa[nxt];
            F[nxt]=Find(fa[F[nxt]]), x=fa[nxt];
        }
    }
    printf("%d\n",Ans);*/

Codeforces#514E(贪心,并查集)的更多相关文章

  1. Codeforces 437D 贪心+并查集

    这个题目让我想起了上次在湘潭赛的那道跪死了的题.也是最值问题,这个也是,有n个动物园 每个都有权值 然后被m条路径相连接,保证图是连通的,然后求所有的p[i][j]之和.i,j为任意两个zoo,pij ...

  2. POJ 1456 Supermarket(贪心+并查集)

    题目链接:http://poj.org/problem?id=1456 题目大意:有n件商品,每件商品都有它的价值和截止售卖日期(超过这个日期就不能再卖了).卖一件商品消耗一个单位时间,售卖顺序是可以 ...

  3. Codeforces 437D The Child and Zoo(贪心+并查集)

    题目链接:Codeforces 437D The Child and Zoo 题目大意:小孩子去參观动物园,动物园分非常多个区,每一个区有若干种动物,拥有的动物种数作为该区的权值.然后有m条路,每条路 ...

  4. codeforces 651E E. Table Compression(贪心+并查集)

    题目链接: E. Table Compression time limit per test 4 seconds memory limit per test 256 megabytes input s ...

  5. Codeforces 731C Socks 并查集

    题目:http://codeforces.com/contest/731/problem/C 思路:并查集处理出哪几堆袜子是同一颜色的,对于每堆袜子求出出现最多颜色的次数,用这堆袜子的数目减去该值即为 ...

  6. codeforces 722C (并查集)

    题目链接:http://codeforces.com/contest/722/problem/C 题意:每次破坏一个数,求每次操作后的最大连续子串和. 思路:并查集逆向操作 #include<b ...

  7. poj1456(贪心+并查集)

    题目链接: http://poj.org/problem?id=1456 题意: 有n个商品, 已知每个商品的价格和销售截止日期, 每销售一件商品需要花费一天, 即一天只能销售一件商品, 问最多能买多 ...

  8. POJ - 1456 贪心+并查集

    做法一:直接贪心,按照利润排序,然后直接尽量给每个活动安排到最晚的时间即可.时间复杂度O(n * d)当d都为10000时,很容易超时.由于这题数据比较水,所有贪心未超时. AC代码 #include ...

  9. poj1456 Supermarket 贪心+并查集

    题目链接:http://poj.org/problem?id=1456 题意:有n个物品(0 <= n <= 10000) ,每个物品有一个价格pi和一个保质期di (1 <= pi ...

随机推荐

  1. php:如何使用PHP排序, key为字母+数字的数组(多维数组)

    你还在为如何使用PHP排序字母+数字的数组而烦恼吗? 今天有个小伙伴在群里问:如何将一个key为字母+数字的数组按升序排序呢? 举个例子: $test = [ 'n1' => 22423, 'n ...

  2. MVC中ajax调用Controller的方法

    1. ajax代码: $.ajax({ async: false, cache: false, type: 'POST', contentType: "application/json&qu ...

  3. 分享知识-快乐自己:Mybatis 基础动态语句

    目录: User: package mlq.bean; /** * 用户实体类 */ public class User { private Integer uId; private String u ...

  4. 分享知识-快乐自己:虚拟机 NET 网络配置

    第一步: 第二步: 第三步:   第四步:   第五步: 第六步: 第七步: 第九步: 第十步: 第十一步: 第十二步:   第十三步: 成功. 第十四步:开启开机自启动网路连接 cd /etc/sy ...

  5. php导出内容到txt并自动弹出下载文件

    php将内容保存到txt文件中,并自动弹出下载文件窗口的方法: $id=array('我爱学习网http://www.5ixuexiwang.com','汇享在线工具箱http://tool.huix ...

  6. BEC listen and translation exercise 42

    These were built for the workers towards the end of the eighteenth century, and they are still furni ...

  7. FJOI2016 神秘数

    题目大意 给定长为$N$一个序列,每次询问一个区间,求最小的不能表示为由区间内若干个(可以是$0$个)数的和的非负整数. 考虑一个可重集合$S$,设抽取$S$中若干个数相加无法得到的最小非负整数为$A ...

  8. 将tomcat7解压版注册为windows系统服务

    一.修改service.bat文件(...tomcat7\bin\service.bat) 该文件中共修改两处即可 ①:在文件的开头加入以下设置,分别是java的安装路径.Tomcat的安装路径及服务 ...

  9. 查看Linux内核版本的命令

    方法一: 命令: uname -a  作用: 查看系统内核版本号及系统名称  方法二:  命令: cat /proc/version 作用: 查看目录"/proc"下version ...

  10. java基础知识(4)---设计模式

    设计模式:解决问题最行之有效的思想.是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. java中有23种设计模 ...