package main import "fmt" var ( time int ) type Graph struct { vertices int adj [][]int } func NewGraph(v int) *Graph { g := &Graph{vertices: v} g.adj = make([][]int, v) return g } func (g *Graph) addEdge(u, v int) { g.adj[u] = append(g.adj[u], v) g.adj[v] = append(g.adj[v], u) } func (g *Graph) APUtil(u int, visited []bool, disc []int, low []int, parent []int, ap []bool) { children := 0 visited[u] = true time++ disc[u] = time low[u] = time for _, v := range g.adj[u] { if !visited[v] { children++ parent[v] = u g.APUtil(v, visited, disc, low, parent, ap) if low[v] >= disc[u] && parent[u] != -1 { ap[u] = true } if low[v] < low[u] { low[u] = low[v] } } else if v != parent[u] { if disc[v] < low[u] { low[u] = disc[v] } } } if parent[u] == -1 && children > 1 { ap[u] = true } } func (g *Graph) FindAP() []int { visited := make([]bool, g.vertices) disc := make([]int, g.vertices) low := make([]int, g.vertices) parent := make([]int, g.vertices) ap := make([]bool, g.vertices) for i := 0; i < g.vertices; i++ { parent[i] = -1 } for i := 0; i < g.vertices; i++ { if !visited[i] { g.APUtil(i, visited, disc, low, parent, ap) } } var result []int for i := 0; i < g.vertices; i++ { if ap[i] { result = append(result, i) } } return result } func main() { g := NewGraph(5) g.addEdge(1, 0) g.addEdge(0, 2) g.addEdge(2, 1) g.addEdge(0, 3) g.addEdge(3, 4) aps := g.FindAP() fmt.Println(aps) }
The articulation points in this graph are vertices 0 and 3. Removing vertex 0 disconnects vertex 1 and 2 from 3 and 4. Removing vertex 3 disconnects vertex 4.
An articulation point is a vertex whose removal increases the number of connected components in the graph, effectively disconnecting parts of the graph.
package main import "fmt" func main() { graph := [][]int{{1, 2}, {0, 2}, {0, 1, 3}, {2}} visited := make([]bool, 4) disc := make([]int, 4) low := make([]int, 4) parent := make([]int, 4) ap := make([]bool, 4) for i := 0; i < 4; i++ { parent[i] = -1 } var time int var APUtil func(u int) APUtil = func(u int) { visited[u] = true time++ disc[u] = time low[u] = time for _, v := range graph[u] { if !visited[v] { parent[v] = u APUtil(v) if low[v] >= disc[u] && parent[u] != -1 { ap[u] = true } if low[v] < low[u] { low[u] = low[v] } } else if v != parent[u] { if disc[v] < low[u] { low[u] = disc[v] } } } } for i := 0; i < 4; i++ { if !visited[i] { APUtil(i) } } fmt.Println(ap) }
The code runs correctly and prints the articulation points array as booleans. Only vertex 2 is an articulation point, so the output is [false false true false].
Vertices 1 and 5 are articulation points. Removing 1 disconnects 3,4,6; removing 5 disconnects 3 and 4.
In a tree, all internal nodes except leaves can be articulation points. Since a tree has at least two leaves, the maximum number of articulation points is N - 2.
