zoukankan      html  css  js  c++  java
  • [BZOJ2799][Poi2012]Salaries

    2799: [Poi2012]Salaries

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 91  Solved: 54
    [Submit][Status][Discuss]

    Description


    给出一棵n个结点的有根树,结点用正整数1~n编号。
    每个结点有一个1~n的正整数权值,不同结点的权值不相同,
    并且一个结点的权值一定比它父结点的权值大(根结点的权值最大,一定是n)。
    现在有些结点的权值是已知的,并且如果一个结点的权值已知,它父结点的权值也一定已知。
    问还有哪些结点的权值能够唯一确定。

    Input


    第一行一个正整数n (n<=1,000,000),表示树的结点数。
    下面共n行,第i行描述编号为i的结点,每行两个整数pi,zi (1<=pi<=n, 0<=zi<=n)。
    pi表示结点i的父结点,如果i=pi,说明i是根结点。
    当zi>0时,表示结点i的权值已知,并且就是zi;当zi=0时,表示结点i的权值未知。
    测试数据保证满足题意,并且存在合法的方案。

    Output

    输出共n行,依次描述每个结点。如果结点i的权值能够唯一确定,第i行输出结点i的权值,否则第i行输出0。

    Sample Input

    10
    2 2
    2 10
    1 0
    2 9
    2 5
    4 0
    6 0
    6 0
    5 0
    5 0

    Sample Output

    2
    2
    10
    1
    9
    5
    8
    0
    0
    0
    0

    HINT

     

    Source

    [Submit][Status][Discuss]


    dfs可以求出每个点最大可能是多少。

    然后就变成个一个填数问题。

    如果$只有一个i,max_i=k$,且1~k之间只剩下了一个数,$v_i=k$

    如果$max_i<=k$的数正好填满1~k则清空1~k。

     1 #include<cstdio>
     2 #define N 1000010
     3 inline int read()
     4 {
     5     int x=0,f=1;char ch=getchar();
     6     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     7     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     8     return x*f;
     9 }
    10 int n,v[N],f[N],fa[N],mx[N];
    11 inline int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    12 int num[N],id[N],all,sum[N];
    13 void dfs(int x)
    14 {
    15     if(mx[x])return;
    16     dfs(fa[x]);
    17     mx[x]=find(mx[fa[x]]-1);
    18     if(++num[mx[x]]==1)
    19     id[mx[x]]=x;
    20 }
    21 int main()
    22 {
    23     n=read();
    24     for(int i=1;i<=n;i++)f[i]=i;
    25     for(int i=1;i<=n;i++)
    26     {
    27         fa[i]=read();
    28         v[i]=read();
    29         if(fa[i]==i)v[i]=n;
    30         if(v[i])f[v[i]]=v[i]-1,mx[i]=v[i];
    31     }
    32     for(int i=1;i<=n;i++)
    33     if(!mx[i])dfs(i);
    34     for(int i=1;i<=n;i++)
    35     sum[i]=sum[i-1]+(f[i]==i);
    36     for(int i=1;i<=n;i++)if(num[i])
    37     {
    38         if(num[i]==1&&sum[i]==all+1)
    39         v[id[i]]=i,all++;
    40         else if(num[i]+all==sum[i])
    41         all=sum[i];
    42         else num[i+1]+=num[i];
    43     }
    44     for(int i=1;i<=n;i++)
    45     printf("%d
    ",v[i]);
    46 }
    View Code
  • 相关阅读:
    HTB-靶机-Charon
    第一篇Active Directory疑难解答概述(1)
    Outlook Web App 客户端超时设置
    【Troubleshooting Case】Exchange Server 组件状态应用排错?
    【Troubleshooting Case】Unable to delete Exchange database?
    Exchange Server 2007的即将生命周期,您的计划是?
    "the hypervisor is not running" 故障
    Exchange 2016 体系结构
    USB PE
    10 months then free? 10个月,然后自由
  • 原文地址:https://www.cnblogs.com/xuruifan/p/5192199.html
Copyright © 2011-2022 走看看