zoukankan      html  css  js  c++  java
  • [BZOJ]4726: [POI2017]Sabota? 树DP

    题解:树dp   对于节点x 如果其及其后代节点 都叛变的话  是可以通过其儿子得到的

          我们假设 其某个儿子及其后代都叛变的时候 需要满足 x<p 那么对于x及其后代节点都叛变 需要满足  max(min(p,1.0*(sz[儿子])/(sz[x]-1)))这样  那么对于所有孩子节点大于k的节点取max  就是所求

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=5e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    
    int fa[MAXN],num[MAXN];
    void dfs(int x,int pre){
        fa[x]=pre;num[x]=1;
        link(x){
    	dfs(j->t,x);
    	num[x]+=num[j->t];
        }
    }
    
    double ans[MAXN];
    
    void dfs1(int x){
        ans[x]=0.000000000;
        link(x){
    	dfs1(j->t);
    	ans[x]=max(ans[x],min(ans[j->t],1.0*num[j->t]/(num[x]-1)));
        }
        if(num[x]==1)ans[x]=1.00000000;
    }
    
    int main(){
        int k,n;n=read();k=read();
        int u;
        inc(i,2,n)u=read(),add(u,i);
        dfs(1,0);dfs1(1);
        double ans1=0.000000;
        inc(i,1,n)if(num[i]>k)ans1=max(ans1,ans[i]);
        printf("%.10f
    ",ans1);
    }
    

      

    4726: [POI2017]Sabota?

    Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge
    Submit: 973  Solved: 399
    [Submit][Status][Discuss]

    Description

    某个公司有n个人, 上下级关系构成了一个有根树。其中有个人是叛徒(这个人不知道是谁)。对于一个人, 如果他
    下属(直接或者间接, 不包括他自己)中叛徒占的比例超过x,那么这个人也会变成叛徒,并且他的所有下属都会变
    成叛徒。你要求出一个最小的x,使得最坏情况下,叛徒的个数不会超过k。
     

    Input

    第一行包含两个正整数n,k(1<=k<=n<=500000)。
    接下来n-1行,第i行包含一个正整数p[i+1],表示i+1的父亲是p[i+1](1<=p[i+1]<=i)。
     

    Output

    输出一行一个实数x,误差在10^-6以内都被认为是正确的。
     

    Sample Input

    9 3
    1
    1
    2
    2
    2
    3
    7
    3

    Sample Output

    0.6666666667

     

  • 相关阅读:
    POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)
    UVaLive 5031 Graph and Queries (Treap)
    Uva 11996 Jewel Magic (Splay)
    HYSBZ
    POJ 3580 SuperMemo (Splay 区间更新、翻转、循环右移,插入,删除,查询)
    HDU 1890 Robotic Sort (Splay 区间翻转)
    【转】ACM中java的使用
    HDU 4267 A Simple Problem with Integers (树状数组)
    POJ 1195 Mobile phones (二维树状数组)
    HDU 4417 Super Mario (树状数组/线段树)
  • 原文地址:https://www.cnblogs.com/wang9897/p/10340358.html
Copyright © 2011-2022 走看看