NOIP2015信息传递

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2015信息传递相关的知识,希望对你有一定的参考价值。

Description

有个同学(编号为 1 到)正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为的同学的信息传递对象是编号为的同学。游戏开始时,每人都只知道自己的生日。之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象)。当有人从别人口中得知自己的生日时,游戏结束。请问该游戏一共可以进行几轮?

Input

输入共 2行。

第 1行包含1个正整数n,表示n个人

第 2 行包含n 个用空格隔开的正整数T1 ,T 2 ,……,Tn , 其中第i个整数Ti表示编号为i

的同学的信息传递对象是编号为 T i 的同学,Ti≤n 且 Ti≠i。

数据保证游戏一定会结束。

Output

输出共 1行,包含  1个整数,表示游戏一共可以进行多少轮。

Sample Input

5

2 4 2 3 1

Sample Output

3

Hint

【输入输出样例 1 说明】

游戏的流程如图所示。当进行完第 3 轮游戏后,4 号玩家会听到 2 号玩家告诉他自己的生日,所以答案为 3。当然,第 3 轮游戏后,2 号玩家、3 号玩家都能从自己的消息来源得知自己的生日,同样符合游戏结束的条件。

 

 

对于 30%的数据,n≤ 200;

对于 60%的数据,n ≤ 2500;

对于 100%的数据,n ≤ 200000。

 

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=200010;
int e[MAXN];
int stack[MAXN];
bool instack[MAXN];
int dfn[MAXN];
int low[MAXN];
int cnt=0,head=0,ans=MAXN;
void tarjan(int u)
{
    stack[++head]=u;
    instack[u]=true;
    low[u]=dfn[u]=++cnt;
    int v=e[u];
    if (!dfn[v])
    {
        tarjan(v);
        low[u]=min(low[u],low[v]);
    }
    else if (instack[v]) low[u]=min(low[u],dfn[v]);
    if (low[u]==dfn[u])
    {
        int sum=0;
        while (u!=v)
        { 
            v=stack[head--]; //v千万不要再定义呀TAT 
            instack[v]=false;
            sum++;
        }
        if (sum<ans&& sum!=1) ans=sum;
    }
}
int main()
{
    int n,x;
    cin>>n;
    for (int i=1;i<=n;i++)
    {
        cin>>x; e[i]=x;
    }
    memset(instack,false,sizeof(instack));
    memset(low,0,sizeof(low));
    memset(dfn,0,sizeof(dfn));
    for (int i=1;i<=n;i++)
        if (!instack[i]) tarjan(i);
    cout<<ans;
    return 0;
}

 

以上是关于NOIP2015信息传递的主要内容,如果未能解决你的问题,请参考以下文章

2105. [NOIP2015] 信息传递

NOIP 2015:信息传递

cogs luogu 2105. [NOIP2015] 信息传递

图论例题1——NOIP2015信息传递

信息传递 NOIP2015 day1 T2

[NOIP2015] 提高组 洛谷P2661 信息传递