• 【BZOJ2799】[Poi2012]Salaries 乱搞


    【BZOJ2799】[Poi2012]Salaries

    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

    题解:这题做法好神啊。。

    一个点的权值唯一确定等价于x>=val且x<=val,那么怎么求最大值呢?如果它父亲的最大值为val,那么从val-1往下找,找到第一个没有被占用的权值就是当前点的最大值。然后怎么求最小值呢?

    我们将所有点按最大值排序,然后从小往大一个一个确定每个点。如果有多个点的最大值=i,那么这些点都无法被确定。如果只有一个点的最大值=i,并且以前已经确定<=i-1的数有i-1个,那么这个点可以被唯一确定。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int maxn=1000010;
    int n,rt,cnt,sum,tot;
    int fa[maxn],to[maxn],next[maxn],head[maxn],v[maxn],ch[maxn],mx[maxn];
    struct node
    {
    	int mx,org;
    }s[maxn];
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    inline void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    void dfs(int x,int mxx)
    {
    	if(!v[x])	s[++tot].mx=mxx,s[tot].org=x;
    	for(int i=head[x];i!=-1;i=next[i])
    	{
    		if(!v[to[i]])	dfs(to[i],mx[mxx-1]);
    		else	dfs(to[i],v[to[i]]);
    	}
    }
    bool cmp(const node &a,const node &b)
    {
    	return a.mx<b.mx;
    }
    int main()
    {
    	n=rd();
    	int i,j,tmp;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)	mx[i]=i;
    	for(i=1;i<=n;i++)
    	{
    		fa[i]=rd(),v[i]=rd(),mx[v[i]]=0;
    		if(fa[i]==i)	rt=i,fa[i]=0;
    		else	add(fa[i],i);
    	}
    	for(i=1;i<=n;i++)	if(!mx[i])	mx[i]=mx[i-1];
    	dfs(rt,n);
    	sort(s+1,s+tot+1,cmp);
    	for(i=j=1;i<=n;i++)
    	{
    		if(mx[i]!=i)	sum++;
    		else
    		{
    			tmp=0;
    			for(;j<=tot&&s[j].mx==i;j++,tmp++);
    			if(tmp==1&&sum==i-1)	v[s[j-1].org]=i;
    			sum+=tmp;
    		}
    	}
    	for(i=1;i<=n;i++)	printf("%d
    ",v[i]);
    	return 0;
    }
  • 相关阅读:
    laravel blog 一
    dede:channelartlist currentstyle高亮显示
    dede调用导航/幻灯
    rmp 安装LNMP环境
    无极分类之子孙树、父辈树
    创始人 密码
    mysql报错显示法文解决办法
    渐变色背景
    laravel sendmail
    工作流系统webservice服务
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7559911.html
Copyright © 2020-2023  润新知