poj 1236 Network of Schools 强联通分量tarjan

题目大意:N(2<N<100)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。2,至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。


解法:

     1:先跑一边tarjian算法。那么我们可以得出每一个学校在哪一个强连通分量里。然后算出入度为0 的强连通分量的个数。就是第一个答案。

     读为0的强连通分量的那些强连通分量连起来。所以算出出度为0和入度为0的最大值,就是第二个的答案。

      3:注意如果强连通分量的个数是一个,那么第二个的答案是0.


一开始以为有多组数据然后就打了not eof,之后就不知道为什么一直WA,后面去掉居然就对了……


代码:

var
  ans,s1,s2,sum,tot,d,i,j,n,x:longint;
  a:array[1..1000,1..1000] of boolean;
  dfn,low,stack,be,rd,cd:array[1..1000] of longint;
  f:array[1..1000] of boolean;

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

procedure tarjan(x:longint);
var
  i,j:longint;
begin
  inc(d);
  dfn[x]:=d;
  low[x]:=d;
  inc(tot);
  stack[tot]:=x;
  f[x]:=true;
  for i:=1 to n do
    if (dfn[i]=0)and(a[x,i])
      then begin
             tarjan(i);
             low[x]:=min(low[x],low[i]);
           end
      else if (f[i])and(a[x,i]) then low[x]:=min(low[x],low[i]);
  if low[x]=dfn[x] then
  begin
    inc(sum);
    repeat
      j:=stack[tot];
      dec(tot);
      f[j]:=false;
      be[j]:=sum;
    until j=x;
  end;
end;

begin
    readln(n);
    fillchar(a,sizeof(a),false);
    for i:=1 to n do
    begin
      read(x);
      while x>0 do
      begin
        a[i,x]:=true;
        read(x);
      end;
      readln;
    end;
    fillchar(f,sizeof(f),false);
    for i:=1 to n do
      if dfn[i]=0 then tarjan(i);
    for i:=1 to n do
      for j:=1 to n do
        if (a[i,j])and(be[i]<>be[j]) then
        begin
          inc(rd[be[j]]);
          inc(cd[be[i]]);
        end;
    for i:=1 to sum do
    begin
      if rd[i]=0 then inc(ans);
      if rd[i]=0 then inc(s1);
      if cd[i]=0 then inc(s2);
    end;
    writeln(ans);
    if sum=1 then
    begin
      s1:=0;
      s2:=0;
    end;
    if s1>s2
      then writeln(s1)
      else writeln(s2);
end.


你可能感兴趣的:(poj 1236 Network of Schools 强联通分量tarjan)