• codevs4511信息传递(Tarjan求环)


    题目描述

    有n个同学(编号为1到n)正在玩一个信息传递的游戏。在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学。

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

    输入输出格式

    输入格式:

    输入共2行。

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

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

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

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

    输出格式:

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

    输入输出样例

    输入样例#1:
    5
    2 4 2 3 1
    输出样例#1:
    3

    说明

    样例1解释

    游戏的流程如图所示。当进行完第 3 轮游戏后, 4 号玩家会听到 2 号玩家告诉他自

    己的生日,所以答案为 3。当然,第 3 轮游戏后, 2 号玩家、 3 号玩家都能从自己的消息

    来源得知自己的生日,同样符合游戏结束的条件。

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

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

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

    //Tarjan 求环模板 
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 200010 
    
    using namespace std;
    int head[maxn],stack[maxn],loop[maxn];
    bool in_stack[maxn];
    int dfn[maxn],low[maxn];
    int n,x,y,a,b,num,cnt,ans,cur,top,loop_num;
    
    struct node
    {
        int from;
        int to;
        int next;
    }e[maxn<<1];
    
    void add(int from,int to)
    {
        e[++num].from=from;
        e[num].to=to;
        e[num].next=head[from];
        head[from]=num;
    }
    
    inline int init()
    {
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    void Tarjan(int u)
    {
        dfn[u]=low[u]=++cnt;
        stack[++top]=u;
        in_stack[u]=true;
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(!dfn[v])
            {
                Tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(in_stack[v])
            {
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u])
        {
            int count=0;
            while(stack[top]!=u)
            {
                count++;
                in_stack[stack[top]]=false;
                top--;
            }
            count++;
            in_stack[stack[top]]=false;
            top--;
            loop_num++;
            loop[loop_num]=count;
        }
    }
    
    int main()
    {
        n=init();
        for(int i=1;i<=n;i++)
        {
            cur=init();
            add(i,cur);
        }
        for(int i=1;i<=n;i++)
          if(!dfn[i]) Tarjan(i);
        ans=0x7ffffff;
        for(int i=1;i<=n;i++)
          if(loop[i]>1)
            ans=min(ans,loop[i]);
        printf("%d
    ",ans);
        return 0;
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    layDate关闭方法
    iOS Crash日志符号化
    图像压缩工具ImageOptim介绍
    UITextField设置光标位置
    Detect backspace in UITextField
    scrollsToTop小结
    查看UIWindows的视图层次
    弹出框适配总结
    关于IOS获取keyBoard键盘是否弹出
    UItableViewCell滑动删除时,调整cell子视图的位置大小
  • 原文地址:https://www.cnblogs.com/L-Memory/p/6372364.html
Copyright © 2020-2023  润新知