NOIP2015 提高组 day1 信息传递

这里写图片描述

分析

用tarjan·强连通分量找一个最小的环

代码

const
  maxn=400100;

type
  arr=record
    x,y:longint;
    next:longint;
end;

var
  status:array[0..maxn] of boolean;
  dfn,low:array[0..maxn] of longint;
  sign:array[1..maxn] of longint;
  edge:array[0..maxn] of arr;
  ls:array[0..maxn] of longint;
  zhan:array[0..maxn] of longint;
  top:longint;
  number:longint;
  n,m,nm:longint;
  shu,shu1:longint;

procedure add(x,y:longint);
begin
  m:=m+1;
  edge[m].x:=x;
  edge[m].y:=y;
  edge[m].next:=ls[x];
  ls[x]:=m;
end;

procedure init;
var
  i,j,k:longint;
begin
  m:=0;
  nm:=0;
  fillchar(ls,sizeof(ls),0);
  readln(n);
  for i:=1 to n do
    begin
      read(j);
      add(i,j);
    end;
end;

function min(x,y:longint):longint;
begin
  if x>y then exit(y)
         else exit(x);
end;

procedure dfs(x:longint);
var
  i,y:longint;
begin
  inc(number);
  inc(top);
  zhan[top]:=x;
  dfn[x]:=number;
  low[x]:=number;
  i:=ls[x];
  while i<>0 do
    begin
      y:=edge[i].y;
      if dfn[y]=0
        then
          begin
            dfs(y);
            low[x]:=min(low[y],low[x]);
          end
        else
          if not status[y]
            then low[x]:=min(dfn[y],low[x]);
      i:=edge[i].next;
    end;
  if dfn[x]=low[x]
    then
      begin
        nm:=nm+1;
        repeat
          sign[nm]:=sign[nm]+1;
          status[zhan[top]]:=true;
          top:=top-1;
        until zhan[top+1]=x;
      end;
end;


procedure main;
var
  i:longint;
  ans:longint;
begin
  number:=0;
  for i:=1 to n do
    if dfn[i]=0 then dfs(i);
  ans:=maxlongint;
  for i:=1 to nm do
    if (sign[i]<ans) and (sign[i]<>1)
      then ans:=sign[i];
  write(ans);
end;

begin
  assign(input,'message.in');
  assign(output,'message.out');
  reset(input);
  rewrite(output);
  init;
  main;
  close(input);
  close(output);
end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值