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.
    
  • 相关阅读:
    【剑指offer】对称的二叉树
    【剑指offer】数组中的逆序对
    【剑指offer】不用加减乘除做加法
    【剑指offer】和为S的连续正数序列
    【剑指offer】删除链表中重复的结点
    【剑指offer】平衡二叉树
    Math.ceil()、Math.floor()和Math.round()
    document.querySelectorAll遍历
    JS选择器querySelector和~All,三个原生选择器
    js 操作select和option常见用法
  • 原文地址:https://www.cnblogs.com/zyx-crying/p/9319579.html
Copyright © 2011-2022 走看看