poj 1236 Network of Schools 强连通分量

题目大意

  N(2<N<100)各学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输,

问题

1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。

2,至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。

 

分析

  先跑一遍taijian算法。然后把一个强连通分量当做一个点,求入度为0的点的个数,就是问题一的答案(因为只有入度为0的强连通分量要分一套软件)。再求出度为0的点的个数,

第二个问题就输出max(入度0,出度0),因为要把这些点连在一起。

 

代码

const
  maxe=50000;
  maxv=1000;

type
  rec=record
        x,y,w,next:longint;
      end;
var
  n,m:longint;
  g:array[1..maxe] of rec;
  ls:array[1..maxv] of longint;
  v,a,ru,cu:array[1..maxv] of longint;
  low,dfn:array[1..maxv] of longint;
  zan:array[1..maxv] of longint;
  tot,ans,tot1:longint;
  i,j,k:longint;

procedure dfs(r:longint);
var
  i,j,k:longint;
begin
  tot:=tot+1;
  zan[tot]:=r;
  v[r]:=1;
  tot1:=tot1+1;
  low[r]:=tot1;
  dfn[r]:=tot1;
  i:=ls[r];
  while i<>0 do
    with g[i] do
      begin
        if dfn[y]=0
          then
            begin
              dfs(y);
              if low[r]>low[y] then low[r]:=low[y];
            end
          else
            if (low[r]>dfn[y]) and (v[y]=1)
              then low[r]:=dfn[y];
        i:=next;
      end;
  if low[r]=dfn[r]
    then
      begin
        ans:=ans+1;
        repeat
          j:=zan[tot];
          tot:=tot-1;
          a[j]:=ans;
          v[j]:=0;
        until j=r;
      end;
end;

begin
  readln(n);
  k:=0;
  ans:=0;
  for i:=1 to n do
    begin
      read(j);
      while j<>0 do
        begin
          k:=k+1;
          with g[k] do
            begin
              x:=i;
              y:=j;
              next:=ls[i];
              ls[i]:=k;
            end;
          read(j);
        end;
    end;
  for i:=1 to n do
    if a[i]=0
      then
        dfs(i);
  for i:=1 to n do
    begin
      j:=ls[i];
      while j<>0 do
        with g[j] do
          begin
            if a[x]<>a[y]
              then
                begin
                  cu[a[x]]:=cu[a[x]]+1;
                  ru[a[y]]:=ru[a[y]]+1;
                end;
            j:=next;
          end;
    end;
  j:=0;
  for i:=1 to ans do
    if ru[i]=0 then j:=j+1;
  writeln(j);
  k:=0;
  for i:=1 to ans do
    if cu[i]=0 then k:=k+1;
  if ans=1 then
    begin
      write(0);
      halt;
    end;
  if k>j then write(k)
         else write(j);
end.



posted @ 2016-06-04 10:05  一个响亮的蒟蒻  阅读(104)  评论(0编辑  收藏  举报