zoukankan      html  css  js  c++  java
  • 【NOIP2015提高组Day1】信息传递

    【问题描述】

    有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.
    
  • 相关阅读:
    CodeForces 7B
    CodeForces 4D
    离散化
    线段树入门
    洛谷 P3951 小凯的疑惑(赛瓦维斯特定理)
    Codeforces 1295D Same GCDs (欧拉函数)
    Codeforces 1295C Obtain The String (二分)
    Codeforces 1295B Infinite Prefixes
    Codeforces 1295A Display The Number(思维)
    Codeforces 1294F Three Paths on a Tree(树的直径,思维)
  • 原文地址:https://www.cnblogs.com/zyx-crying/p/9319579.html
Copyright © 2011-2022 走看看