BZOJ 1051:[HAOI2006]受欢迎的牛(强连通分量)

                                                       受欢迎的牛
Description
每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。
Input
第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可能出现多个A,B)
Output
一个数,即有多少头牛被所有的牛认为是受欢迎的。
Sample Input
3 3
1 2
2 1
2 3
Sample Output
1
HINT
100%的数据N<=10000,M<=50000

分析:

  求出图的强连通分量并缩点,再检查出度为0点的个数,若为不为1,说明无解,若个数为1,输出那个点代表的强连通分量点的个数。

代码:

program cow;
type
  point=^node;
    node=record
      data:longint;
      next:point;
    end;
var
  a,b:array[0..10000]of point;
  f,q,c:array[0..10000]of longint;
  w,g:array[0..10000]of boolean;
  n,i,m,s,t,x,y,v:longint; p:point;
procedure dfs1(x:longint);
var p:point;
begin
  g[x]:=true; new(p); p:=a[x];
  while p<>nil do
   begin
     if g[p^.data]=false then dfs1(p^.data); p:=p^.next;
   end;
  t:=t+1; q[t]:=x;
end;
procedure dfs2(x,y:longint);
var p:point;
begin
  g[x]:=true; new(p); p:=b[x];
  while p<>nil do
   begin
     if g[p^.data]=false then dfs2(p^.data,y); p:=p^.next;
   end;
  s:=s+1; f[x]:=y;
end;
begin
  readln(n,m); t:=0;
  for i:=1 to m do
   begin
     readln(x,y);
     new(p);  p^.data:=y; p^.next:=a[x]; a[x]:=p;
     new(p);  p^.data:=x; p^.next:=b[y]; b[y]:=p;
   end;
  for i:=1 to n do if g[i]=false then dfs1(i);
  fillchar(g,sizeof(g),false);
  for i:=t downto 1 do
    begin
      x:=q[i];
      if g[x]=false then
       begin
         s:=0; dfs2(x,x);c[x]:=c[x]+s;
       end;
    end;
  fillchar(w,sizeof(w),1);
  for i:=1 to n do
   begin
     new(p);p:=a[i]; v:=0;
     while p<>nil do
      begin
        if f[i]<>f[p^.data] then begin v:=1;break;  end;  p:=p^.next;
      end;
     if v=1 then w[f[i]]:=false;
   end;
  for i:=1 to n do if f[i]<>i then w[i]:=false;s:=0;
  for i:=1 to n do
  if w[i]=true then begin inc(s); t:=c[i]; end;
  if s=1 then writeln(t) else writeln(-1);
end.
View Code

 

posted @ 2015-11-05 13:32  QTY_YTQ  阅读(...)  评论(... 编辑 收藏