diff --git a/gap/attr.gi b/gap/attr.gi index 6977db33e..2244742bb 100644 --- a/gap/attr.gi +++ b/gap/attr.gi @@ -13,8 +13,8 @@ InstallMethod(ArticulationPoints, "for a digraph", [IsDigraph], function(digraph) - local copy, nbs, counter, visited, num, low, parent, points, v_stack, - w_stack, depth, 1st_root_nb, v, w, i; + local copy, nbs, counter, visited, num, low, parent, points, points_seen, + stack, depth, v, w, i; if (HasIsConnectedDigraph(digraph) and not IsConnectedDigraph(digraph)) or DigraphNrVertices(digraph) <= 1 then @@ -32,51 +32,54 @@ function(digraph) low := []; parent := [1]; points := []; - v_stack := [1]; - w_stack := [0]; + points_seen := BlistList([1 .. DigraphNrVertices(copy)], []); + stack := [[1, 0]]; depth := 1; - 1st_root_nb := First(nbs[1], x -> not x = 1); while depth > 1 or not visited[1] do - if visited[v_stack[depth]] then + v := stack[depth][1]; + if visited[v] then depth := depth - 1; - v := v_stack[depth]; - w := nbs[v][w_stack[depth]]; - if v = 1 then - if w <> 1st_root_nb then - Add(points, v); - fi; - elif low[w] >= num[v] then + v := stack[depth][1]; + w := nbs[v][stack[depth][2]]; + if v <> 1 and low[w] >= num[v] and not points_seen[v] then + points_seen[v] := true; Add(points, v); fi; if low[w] < low[v] then low[v] := low[w]; fi; else - v := v_stack[depth]; visited[v] := true; counter := counter + 1; num[v] := counter; low[v] := counter; fi; - for i in [w_stack[depth] + 1 .. Length(nbs[v])] do + i := PositionProperty(nbs[v], w -> w <> v, stack[depth][2]); + while i <> fail do w := nbs[v][i]; - if w <> v then - if not visited[w] then - parent[w] := v; - w_stack[depth] := i; - depth := depth + 1; - v_stack[depth] := w; - w_stack[depth] := 0; - break; - elif parent[v] <> w and num[w] < low[v] then - low[v] := num[w]; + if not visited[w] then + parent[w] := v; + stack[depth][2] := i; + depth := depth + 1; + if not IsBound(stack[depth]) then + stack[depth] := []; fi; + stack[depth][1] := w; + stack[depth][2] := 0; + break; + elif parent[v] <> w and num[w] < low[v] then + low[v] := num[w]; fi; + i := PositionProperty(nbs[v], w -> w <> v, i); od; od; if counter = DigraphNrVertices(digraph) then + i := Position(parent, 1, 1); + if i <> fail and Position(parent, 1, i) <> fail then + Add(points, 1); + fi; SetIsConnectedDigraph(digraph, true); return points; else diff --git a/tst/standard/attr.tst b/tst/standard/attr.tst index c12c82e2f..5e5a60bd3 100644 --- a/tst/standard/attr.tst +++ b/tst/standard/attr.tst @@ -1508,6 +1508,23 @@ gap> ArticulationPoints(DigraphFromGraph6String("FlCX?")); gap> ArticulationPoints(Digraph([[2, 4, 5], [1, 4], [4, 7], [1, 2, 3, 5, 6, 7], > [1, 4], [4, 7], [3, 4, 6]])); [ 4 ] +gap> gr := DigraphFromSparse6String( +> ":~?@V`OINBg_McouHAxQD@gyYEW}Q_@_YdgE`?OgZgpEbfYQKDGqiDQEI`wGdjoADGZG\ +> FIJONFQSplq]y@IwvbPKhMh}JGK?OLzW{agKKfRCtarqTGayQGb]rMIurapkxPG?RGcI]\ +> IBtB_`EQKJ@LmxlL_?k^QieOkB|T"); + +gap> ArticulationPoints(gr); +[ 30, 27, 23, 21, 63, 12, 73, 52, 75, 84, 11, 17, 60, 19, 87, 15, 69, 76, 42, + 61, 59, 66, 68, 8, 51, 41, 37, 36, 18, 79, 3, 46, 1 ] +gap> IsDuplicateFree(last); +true +gap> ForAll(ArticulationPoints(gr), +> x -> not IsConnectedDigraph(DigraphRemoveVertex(gr, x))); +true +gap> Set(ArticulationPoints(gr)) +> = Filtered(DigraphVertices(gr), +> x -> not IsConnectedDigraph(DigraphRemoveVertex(gr, x))); +true #T# HamiltonianPath gap> g := Digraph([]);