zoukankan      html  css  js  c++  java
  • [NOIp 2015]信息传递

    Description

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

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

    Input

    输入共2行。

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

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

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

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

    Output

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

    Sample Input

    5
    2 4 2 3 1

    Sample Output

    3

    Hint

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

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

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

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

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

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

    题解

    抓取有用信息:

    1、有向图;
    2、每个点只有一条出边。

    100分算法:

    1、有向图很容易想到$Floyd$;

    2、每个点只有一条出边意味着边数是$O(n)$的,而且每一个环都没有出边;大家可以各种画图感受一下这张图的性质;

    3、最后得到的结论就是图的中间有若干个环,周围的点各种连向环;

    4、我们的目的是找出最小的环,那么我们只要把每个环旁边的支链去掉,然后求环的长度就行了;

    5、去掉支链可以用$BFS$;

    6、为什么是$BFS$?因为除了环以外的部分都有鲜明的层次性;

    7、具体做法:从没有入边的点开始搜,不断地删点,然后更新剩下的还有哪些点没有入边;删点删到剩下的都是有入边的点,就是一堆环了;

    8、然后$DFS$对每个环求环长,结果取最小值即为答案。
    也可以用强连通分量做。
    另外大家可以去学一个叫基环内向树的东西。

     1 #include<set>
     2 #include<map>
     3 #include<ctime>
     4 #include<cmath>
     5 #include<queue>
     6 #include<stack>
     7 #include<vector>
     8 #include<cstdio>
     9 #include<string>
    10 #include<cstring>
    11 #include<cstdlib>
    12 #include<iostream>
    13 #include<algorithm>
    14 #define LL long long
    15 #define Max(a,b) ((a)>(b) ? (a):(b))
    16 #define Min(a,b) ((a)<(b) ? (a):(b))
    17 using namespace std;
    18 const int N=200000;
    19 const int INF=~0u>>1;
    20 
    21 int n;
    22 int to[N+5];
    23 int in[N+5];
    24 queue<int>Q;
    25 
    26 int main()
    27 {
    28     scanf("%d",&n);
    29     for (int i=1;i<=n;i++) scanf("%d",&to[i]),in[to[i]]++;
    30     for (int i=1;i<=n;i++)
    31       if (!in[i]) Q.push(i);
    32     while (!Q.empty())
    33     {
    34       int u=Q.front();Q.pop();
    35       in[to[u]]--;
    36       if (!in[to[u]]) Q.push(to[u]);
    37     }
    38     int ans=INF;
    39     for (int i=1;i<=n;i++)
    40     if (in[i])
    41     {
    42         in[i]=0;
    43         int cnt=1;
    44         for (int j=to[i];j!=i;j=to[j]) cnt++,in[j]=0;
    45         ans=Min(ans,cnt);
    46     }
    47     printf("%d
    ",ans);
    48     return 0;
    49 }
  • 相关阅读:
    VUE学习日记(十八) ---- 传递数据
    VUE学习日记(十七) ---- 组件数据函数
    VUE学习日记(十六) ---- 表行组件
    DataGridView控件使用Demo
    C# ADO.NET连接字符串详解
    SQL Server management studio使用sa连接时报错与伺服器的连接已成功,但在登入程序是发生错误
    Oracle Rac to Rac One Node
    online创建索引中途取消导致索引无法删除解决办法
    oracle常用hint添加
    C# url的编码解码,xml和json的序列化和反序列化
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/7452538.html
Copyright © 2011-2022 走看看