您的位置:首页 > 其它

【NOIP2015提高组Day1】信息传递

2016-09-08 17:54 330 查看
【问题描述】

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


【输入格式】

输入文件名为message.in。 输入共2行。  第 1 行包含 1 个正整数n,表示n个人。  第 2 行包含n个用空格隔开的正整数T1,T2,… ,Tn,其中第Ti个整数表示编号为i 的同学的信息传递对象是编号为Ti的同学,Ti≤n且Ti≠i。  数据保证游戏一定会结束。


【输出格式】

输出文件名为message.out。  输出共1行,包含1个整数,表示游戏一共可以进行多少轮。


【题解】

一个赤裸裸的强连通分量啊!!


【代码】

type
arr=record
y,next:longint;
end;
var
e:array [0..200001] of arr;
n,ans,tail,en,dn,bn:longint;
v:array [0..200001] of boolean;
f,ls,a,low,dfn:array [0..200001] of longint;
procedure add(o,p:longint);
begin
inc(en);
with e[en] do
begin
y:=p;
next:=ls[o];
ls[o]:=en;
end;
end;

function min(o,p:longint):longint;
begin
if o<p then exit(o);
exit(p);
end;

procedure dfs(x:longint);
var
i,j,sz:longint;
begin
inc(tail);
f[tail]:=x;
v[x]:=true;
inc(dn);
low[x]:=dn; dfn[x]:=dn;
i:=ls[x];
while i<>0 do
with e[i] do
begin
if dfn[y]=0 then
begin
dfs(y);
low[x]:=min(low[x],low[y]);
end else
if v[y] then
low[x]:=min(low[x],dfn[y]);
i:=next;
end;
if low[x]=dfn[x] then
begin
inc(bn);
sz:=0;
repeat
inc(sz);
j:=f[tail];
dec(tail);
v[j]:=false;
a[j]:=bn;
until j=x;
if sz>1 then ans:=min(ans,sz);
end;
end;

procedure tarjan;
var
i:longint;
begin
ans:=maxlongint;
fillchar(dfn,sizeof(dfn),0);
fillchar(low,sizeof(low),0);
bn:=0; dn:=0; tail:=0;
for i:=1 to n do
if dfn[i]=0 then
dfs(i);
end;

procedure init;
var
i,y:longint;
begin
readln(n);
for i:=1 to n do
begin
read(y);
add(i,y);
end;
end;

begin
assign(input,'message.in');
assign(output,'message.out');
reset(input);
rewrite(output);
init;
tarjan;
write(ans);
close(input);
close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息