信息传递
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 的同一主机活动上传递数据并更新片段文本/按钮
为啥我的 C 代码片段不起作用?简化版可以。为 unsigned long long 传递不带 VA_ARGS 的 args