UOJ#67 新年的毒瘤(Tarjan算法求割点)

题意简述

给定一个 n 个点, m 条边( n , m 105 )的无向连通图(无重边和自环)。在图中,若一个点为毒瘤节点,则删去该点后原图将变为一棵树。求所有毒瘤节点。

分 析

1.一棵树是一个含 n 个点 n1 条边的无向连通图。
2.删去该点后原图应连通且边数变为 n2 条。
3.毒瘤节点不能为图的割点且度数应为 m(n2)

实现

Tarjan算法求割点

type
  edge=record
  re,next:longint;
end;
var
cnt,x,y,i,n,m,ans:longint;
e:array[0..200020] of edge;
du,dfn,low,f:array[0..100010] of longint;
vs,cut:array[0..100010] of boolean;
procedure add(x,y:longint);
begin
  inc(cnt);inc(du[x]);
  with e[cnt] do
  begin
    re:=y;next:=f[x];
  end;
  f[x]:=cnt;
end;
function min(x,y:longint):longint;
begin if xthen exit(x);exit(y);end;
procedure dfs(x,fa:longint);
var
tot,tmp:longint;
begin
  vs[x]:=true;tot:=0;
  inc(cnt);dfn[x]:=cnt;low[x]:=cnt;
  tmp:=f[x];
  while tmp<>0 do
  begin
    with e[tmp] do
    if re<>fa then
    begin
      if not vs[re] then
      begin
        inc(tot);
        dfs(re,x);
        low[x]:=min(low[x],low[re]);
        if low[re]>=dfn[x] then cut[x]:=true;
      end
      else low[x]:=min(low[x],dfn[re]);
    end;
    tmp:=e[tmp].next;
  end;
  if (x=1)and(tot=1) then cut[1]:=false;
end;

BEGIN
  readln(n,m);
  for i:=1 to m do
  begin
    readln(x,y);
    add(x,y);add(y,x);
  end;
  cnt:=0;
  dfs(1,0);
  for i:=1 to n do
  if not cut[i] and (du[i]=m-(n-2)) then inc(ans);
  writeln(ans);
  for i:=1 to n do
  if not cut[i] and (du[i]=m-(n-2)) then write(i,' ');
  writeln;
END.

你可能感兴趣的:(解题报告)