信息传递

Posted 【對策局】

tags:

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

【题目描述】

有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;
}

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

导航项目已选中,传递额外信息

在 NavigationUI 的同一主机活动上传递数据并更新片段文本/按钮

如何使用Android片段管理器传递变量[重复]

将数据从底部工作表对话框片段传递到片段

从另一个活动的活动中的片段传递数据

为啥我的 C 代码片段不起作用?简化版可以。为 unsigned long long 传递不带 VA_ARGS 的 args