POJ2553 The Bottom of a Graph Tarjan 矩阵 pascal 解题报告

第三道tarjan,有了前两道题的经验,很快就写完了,但是万恶的初始化。。。。。。

题目大意如下:给出若干个测试样例,当奇数行的N不为0时,有两个数N,M,代表有N个点M条边,然后偶数行会有M条边的信息,求出每个数据里缩点后出度为0的所有点,把所有这些点集里的点标记后按升序输出,如果N=0则结束程序。其中1<=n,m<=5000

不想解释太多,这道题还是比较水的,关键是要在输出时把所有的点进行升序输出而并非对于每个强连通分量

要注意初始化,其实本来可以1A的,就是没有注意初始化,然后各种爆时间爆空间爆栈。。。。。。

var
  g:array[1..6000,1..6000] of 0..1;
  f,v,wr:array[1..6000] of boolean;
  dfn,low:array[1..6000] of integer;
  stack:array[1..6000] of integer;
  sd,cd:array[1..6000] of integer;
  n,m,i,x,y,deep,top,ans,j:integer;
  function min(a,b:integer):integer;
  begin
    if a<b then exit(a) else exit(b);
  end;
  procedure pop(k:integer);
  begin
    while stack[top+1]<>k do
    begin
      sd[stack[top]]:=ans;    //缩点
      f[stack[top]]:=false;
      dec(top);
    end;
  end;
  procedure dfs(k:integer);
  var
    i:integer;
  begin
    inc(deep);
    dfn[k]:=deep; low[k]:=deep;
    inc(top);
    stack[top]:=k;
    v[k]:=true; f[k]:=true;
    for i:=1 to n do
    begin
      if g[k,i]=1 then
      begin
        if v[i]=false then
        begin
          dfs(i);
          low[k]:=min(low[k],low[i]);
        end
        else
          if f[i] then low[k]:=min(low[k],dfn[i]);
      end;
    end;
    if dfn[k]=low[k] then begin inc(ans); pop(k); end;
  end;
begin
  read(n);
  while n<>0 do
  begin
    read(m);
    fillchar(g,sizeof(g),0);
    fillchar(wr,sizeof(wr),false);
    fillchar(v,sizeof(v),false);
    fillchar(f,sizeof(f),false);
    fillchar(sd,sizeof(sd),0);
    fillchar(cd,sizeof(cd),0);
    fillchar(stack,sizeof(stack),0);
    fillchar(dfn,sizeof(dfn),0);
    fillchar(low,sizeof(low),0);
    ans:=0; deep:=0; top:=0;                //记得初始化,最后这一行坑了我10几次提交
    for i:=1 to m do
    begin
      read(x,y);
      g[x,y]:=1;
    end;
    for i:=1 to n do
      if v[i]=false then dfs(i);           //Tarjan
    for i:=1 to n do
      for j:=1 to n do
        if (g[i,j]=1) and (sd[i]<>sd[j]) then inc(cd[sd[i]]);     //记录出度
    for i:=1 to ans do
      if cd[i]=0 then
        for j:=1 to n do
          if sd[j]=i then wr[j]:=true;           //标记出度为0的所有点集的所有点
    for i:=1 to n do if wr[i]=true then write(i,' ');
    writeln;
    read(n);
  end;
end.


其实用矩阵的时间和空间复杂度会比较高,时间和空间都只是刚刚好卡点而已,链接表有些细节的地方还在改,但是矩阵相对比较容易理解额。。。。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值