10551: 排队

题目描述

聪明的海狸先生病了,所以他得去看医生。医生叫海狸先生去照心电图,但是心电图室门前排起了好长的队。海狸先生只好跟着排了队。
站了3小时后,聪明的海狸先生发现很多人并不清楚谁应该站在他们自己前面,这可导致队伍变得一团糟。于是海狸先生数了下,发现队伍中包括他自己一共有n个人,他将这些人从1到n编号,同时他记自己的编号为x。之后,他走到每个人面前,问他在队伍中他前面应该是谁。当然,有人是不知道的,那他可能下一个就能进心电图室,也可能还要等很长很长的时间……
正如你猜到的那样,海狸先生想叫你根据他问问题的结果确定他自己在队伍中的所有可能的位置。

 

 

输入

第一行有两个正整数n和x,代表队伍的总人数和海狸先生的编号。接下来一行n个非负整数a1, a2, ..., an,第i个数ai若为正,则表示编号为i的人前面的人的编号,否则表示第i个人不确定他前面是否排着人以及排着的是谁(如果有),数据保证给定的关系没有环,且任何一个人最多只会被一个人跟在后面。

 

输出

按照从小到大的顺序输出海狸先生所有可能的位置,一行输出一个。

 

样例输入

复制样例数据

6 1
2 0 4 0 6 0

样例输出

2
4
6

 

提示

对于第二个样例,可能的从前到后的排队顺序只有3 2 1 6 5 4以及6 5 4 3 2 1,其中海狸先生编号为2,分别位于队伍中第2个位置和第5个位置。
【数据范围及约定】
对于20%的数据,n ≤ 10,
对于50%的数据,最多有10个人不知道自己的排队状况。
对于100%的数据,1 ≤ x ≤ n ≤ 1000,0 ≤ ai ≤ n,数据保证给定的关系没有环,且任何一个人最多只会被一个人跟在后面。

 

 

 

来源/分类

衡水2018NOIP考前集训 

#include <bits/stdc++.h>
 
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
#define lowbit(x)  x&(-x)
typedef pair<int,int>  pa;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
int n,x,be,flag;
int fa[1050],len[1050],dptmp[1050]={0},dp[1050]={0};
vector<int> vv;
int getpos(int now)
{
    if(dptmp[now])
    {
        return dptmp[now];
    }
    if(now==x)
    {
        flag=1;
    }
    if(fa[now]==0)
    {
        return 1;
    }
    return dptmp[now]=getpos(fa[now])+1;
}
int main()
{
    scanf("%d %d",&n,&x);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&be);
        if(be!=0)
        {
            fa[i]=be;//i的前面是谁
            len[be]++;//i后面确定的长度是多少
        }
    }
    for(int i=1; i<=n; i++)
    {
        if(!len[i])
        {
            flag=0;
            int tmp=getpos(i);
            if(!flag)
            {
                vv.push_back(tmp);
            }
        }
    }
    for(int i=0; i<vv.size(); i++)
    {
        for(int j=n; j>=vv[i]; j--)
        {
            dp[j]=max(dp[j],dp[j-vv[i]]+vv[i]);
        }
    }
    int ansx=getpos(x);
    for(int i=0; i<=n; i++)
    {
        if(i==dp[i])
        {
            printf("%d\n",i+ansx);
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值