bzoj 1638 dfs

题意:n个点,m条有向边,从每个入度为0的点走到编号为n的点,求经过次数最多的边的经过次数

根据乘法原理易知:一条边(a,b)的经过次数=入度为0的点到a的路径条数*b到编号为n的路径条数

正反两次建图,分别跑两次dfs处理出即可

pascal同志记得开Q-(也可能是本蒟蒻写丑了)

{$Q-}
type
        rec=record
            a,b:longint;
end;

var
        n,m,ll          :longint;
        last,f,g        :array[0..5010] of longint;
        pre,other       :array[0..50010] of longint;
        i               :longint;
        ans             :longint;
        l               :array[0..50010] of rec;
procedure connect(x,y:longint);
begin
   inc(ll);
   pre[ll]:=last[x];
   last[x]:=ll;
   other[ll]:=y;
end;

procedure dfs1(x:longint);
var
        p,q:longint;
begin
   q:=last[x];
   if q=0 then
   begin
      f[x]:=1; exit;
   end;
   while (q<>0) do
   begin
      p:=other[q];
      if f[p]=0 then dfs1(p);
      inc(f[x],f[p]);
      q:=pre[q];
   end;
end;

procedure dfs2(x:longint);
var
        p,q:longint;
begin
   q:=last[x];
   if q=0 then
   begin
      g[x]:=1; exit;
   end;
   while (q<>0) do
   begin
      p:=other[q];
      if g[p]=0 then dfs2(p);
      inc(g[x],g[p]);
      q:=pre[q];
   end;
end;

begin
   read(n,m);
   for i:=1 to m do read(l[i].a,l[i].b);
   for i:=1 to m do connect(l[i].b,l[i].a);
   dfs1(n);
   ll:=0;
   for i:=1 to n do last[i]:=0;
   for i:=1 to m do connect(l[i].a,l[i].b);
   for i:=1 to n do if g[i]=0 then dfs2(i);
   ans:=0;
   for i:=1 to m do
     if (f[l[i].a]*g[l[i].b]>ans) then ans:=f[l[i].a]*g[l[i].b];
   writeln(ans);
end.
——by Eirlys
bzoj 1638 dfs_第1张图片


你可能感兴趣的:(bzoj,dfs,bzoj,搜索)