zoukankan      html  css  js  c++  java
  • 信息传递

    【题目描述】

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

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

    现询问该游戏一共可以进行几轮。

    【输入描述】

    输入共两行。

    第一行输入一个正整数n,表示人数;

    第二行输入n个正整数T1、T2、······、Tn,第i个整数Ti表示编号为i的同学的信息传递对象是编号为Ti的同学(Ti ≤ n,Ti ≠ i)。

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

    【输出描述】

    输出一个整数,表示游戏一共可以进行几轮。

    【样例输入】

    5

    2 4 2 3 1

    【样例输出】

    3

    【数据范围及提示】

    样例游戏的流程如图所示:

    当进行完第3轮游戏后,4号玩家会从2号玩家口中得知自己的生日,所以答案为3。当然,第3轮游戏后,2号玩家、3号玩家都能够从自己的消息来源得知自己的生日,同样符合游戏结束的条件。

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

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

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

    DFS:

    源代码:
    
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,Now,Max=0x3fffffff,i[500001],v[500001],u[500001];
    void DFS(int T,int Num)
    {
        if (v[T])
        {
            if (u[T]==Now) //同在一环,深度差即为环长。
              Max=min(Max,Num-v[T]);
            return;
        }
        u[T]=Now;
        v[T]=Num;
        DFS(i[T],Num+1);
        return;
    }
    int main() //本蒟蒻感觉此乃一寻找最短环的新算法!
    {
        scanf("%d",&n);
        for (int a=1;a<=n;a++)
          scanf("%d",&i[a]);
        for (int a=1;a<=n;a++)
        {
            Now=a;
            if (!v[a])
            {
                u[a]=Now; //所属编号。
                v[a]=1; //深度。
                DFS(i[a],2);
            }
        }
        printf("%d",Max);
        return 0;
    }
    
    /*
        解题思路:
            同理于Tarjan算法,通过标记深度与根本节点来深搜最小环。
        反思教训:
            千万不要怂!抓住题目突破口并高效思考相似算法。
    */

    Tarjan解法:

    源代码:
    
    #include<cstdio>
    #include<stack>
    #include<algorithm>
    using namespace std;
    stack <int> S;
    int n,Num(0),Ans=1000000000,i[200001],j[200001],To[200001];
    bool Instack[200001]={0};
    void Tarjan(int t) //就是一个裸的Tarjan()。
    {
        i[t]=j[t]=++Num;
        S.push(t);
        Instack[t]=true;
        int T=To[t];
        if (!j[T])
        {
            Tarjan(T);
            i[t]=min(i[t],i[T]);
        }
        else
          if (Instack[T])
            i[t]=min(i[t],j[T]);
        if (i[t]==j[t])
        {
            int Sum(0);
            while (t!=T)
            {
                T=S.top();
                S.pop();
                Instack[T]=false;
                Sum++;
            }
            if (Sum!=1)
              Ans=min(Ans,Sum);
        }
    }
    int main()
    {
        scanf("%d",&n);
        for (int a=1;a<=n;a++)
          scanf("%d",&To[a]);
        for (int a=1;a<=n;a++)
          if (!j[a])
            Tarjan(a);
        printf("%d",Ans);
        return 0;
    }
  • 相关阅读:
    JavaFX 1.2 SDK 发布,增加 Linux 及 OpenSolaris 支持
    JSF 2.0 通过最终投票
    NetBeans 时事通讯(刊号 # 57 May 27, 2009)
    “C语言” 读书札记(六)之[Linux下C语言编程环境Make命令和Makefile] 川山甲 博客园
    [转]宽字符的介绍
    【语法回顾】C++STL:string类型 ATP_ 博客园
    Using the C/C++ Garbage Collection Library, libgc
    Makefile学习笔记 我的CPP之路 C++博客
    伍迷创意随想集 之 杯具拥有个性,个性成就杯具 伍迷 博客园
    知哈希算法——找出相似的图片
  • 原文地址:https://www.cnblogs.com/Ackermann/p/5836245.html
Copyright © 2011-2022 走看看