poj 2186 Popular Cows 强连通分量

题目大意

  n头奶牛,给出若干个欢迎关系a b,表示a欢迎b,欢迎关系是单向的,但是是可以传递的。另外每个奶牛都是欢迎他自己的。求出被所有的奶牛欢迎的奶牛的数目

 

分析

  先跑一遍taijian算法。那么出度为0的强连通分量代表的就是受其他奶牛欢迎的,但是如果出度为0的强连通分量的个数大于1那么则无解。因为将至少有两个分量里的奶牛互相不喜欢(因为他们的出度为0,不连接其他点,就不喜欢另一个同样情况的强连通分量)。所以我们的算法就是如果出度为0的强连通分量的个数是1.那么我们算出这里面点的个数就是最后的答案。

 

代码

const
  maxe=500000;
  maxv=20000;

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,m);
  k:=0;
  ans:=0;
  for i:=1 to m do
    begin
      readln(j,k);
      with g[i] do
        begin
          x:=j;
          y:=k;
          next:=ls[x];
          ls[x]:=i;
        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;
  k:=0;
  for i:=1 to ans do
    if cu[i]=0 then k:=k+1;
  if k<>1
    then
      begin
        write(0);
        halt;
      end;
  k:=0;
  for i:=1 to ans do
    if cu[i]=0 then k:=i;
  j:=0;
  for i:=1 to n do
    if a[i]=k then j:=j+1;
  write(j);
end.


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