poj 2186 Popular Cows 强联通分量tarjan/Kosaraju

来源:互联网 发布:朝鲜核问题的影响 知乎 编辑:程序博客网 时间:2024/05/22 13:10

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


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


代码(tarjan):

const  maxn=10005;var  n,m,i,j,x,ans,sum,tot,d,u:longint;  last,stack,dfn,low,rd,cd,belong:array[1..maxn] of longint;  f:array[1..maxn] of boolean;  next,y:array[1..maxn*5] of longint;procedure init;var  i:longint;begin  tot:=0;  sum:=0;  d:=0;  ans:=0;  fillchar(dfn,sizeof(dfn),0);  fillchar(low,sizeof(low),0);  fillchar(rd,sizeof(rd),0);  fillchar(cd,sizeof(cd),0);  fillchar(f,sizeof(f),false);  fillchar(last,sizeof(last),0);  readln(n,m);  for i:=1 to m do  begin    readln(x,y[i]);    next[i]:=last[x];    last[x]:=i;  end;end;function min(x,y:longint):longint;begin  if x<y then exit(x)         else exit(y);end;procedure tarjan(x:longint);var  i:longint;begin  inc(d);  dfn[x]:=d;  low[x]:=d;  inc(tot);  stack[tot]:=x;  f[x]:=true;  i:=last[x];  while i<>0 do  begin    if dfn[y[i]]=0      then begin             tarjan(y[i]);             low[x]:=min(low[x],low[y[i]]);           end      else if f[y[i]] then low[x]:=min(low[x],dfn[y[i]]);    i:=next[i];  end;  if low[x]=dfn[x] then  begin    inc(sum);    repeat      i:=stack[tot];      dec(tot);      f[i]:=false;      belong[i]:=sum;    until i=x;  end;end;begin  while not eof do  begin    init;    for i:=1 to n do      if dfn[i]=0 then tarjan(i);    for i:=1 to n do    begin      j:=last[i];      while j>0 do      begin        if belong[i]<>belong[y[j]] then        begin          inc(cd[belong[i]]);          inc(rd[belong[y[j]]]);        end;        j:=next[j];      end;    end;    j:=0;    for i:=1 to sum do      if cd[i]=0 then      begin        inc(j);        u:=j;      end;    for i:=1 to n do      if belong[i]=u then inc(ans);    if j=1      then writeln(ans)      else writeln(0);  end;end.
</pre><pre code_snippet_id="1631039" snippet_file_name="blog_20160331_1_5072205" name="code" class="plain">
代码(Kosaraju):
var  i,j,e,f1,e1,x,y,n,m,tot,u,ans:longint;  v:array[1..10000] of boolean;  last,f,belong,d:array[1..10000] of longint;  side:array[1..100000] of record    x,y,next:longint;  end;procedure add(x,y:longint);begin  inc(e);  side[e].x:=x;  side[e].y:=y;  side[e].next:=last[x];  last[x]:=e;end;procedure dfs(x:longint);var  i:longint;begin  v[x]:=false;  i:=last[x];  while i>0 do    with side[i] do    begin      if v[y] then dfs(y);      i:=next;    end;  if tot=0    then begin           inc(f1);           f[f1]:=x;         end    else belong[x]:=tot;end;begin  readln(n,m);  for i:=1 to m do  begin    readln(x,y);    add(x,y);  end;  fillchar(v,sizeof(v),true);  for i:=1 to n do    if v[i] then dfs(i);  e1:=e;  fillchar(v,sizeof(v),true);  fillchar(last,sizeof(last),0);  for i:=1 to e do    add(side[i].y,side[i].x);  for i:=n downto 1 do    if v[f[i]] then    begin      inc(tot);      dfs(f[i]);    end;  for i:=1 to e1 do    with side[i] do      if belong[x]<>belong[y] then inc(d[belong[x]]);  j:=0;  for i:=1 to tot do    if d[i]=0 then    begin      inc(j);      u:=i;    end;  for i:=1 to n do    if belong[i]=u then inc(ans);  if j>1    then writeln(0)    else writeln(ans);end.



0 0
原创粉丝点击