Skip to content

Commit f275e29

Browse files
Migrated Graph-3 bundle
1 parent a617e2f commit f275e29

16 files changed

+355
-1
lines changed
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
---
2+
title: Bridges and Articulation Points
3+
tags:
4+
- Bridge
5+
- Articulation Point
6+
- Cut Vertex
7+
- Cut Edge
8+
- Graph
9+
---
10+
11+
## DFS Order
12+
13+
**DFS order** is traversing all the nodes of a given graph by fixing the root node in the same way as in the DFS algorithm, but without revisiting a discovered node. An important observation here is that the edges and nodes we use will form a **tree** structure. This is because, for every node (**except the root**), we only arrive from another node, and for the **root** node, we do not arrive from any other node, thus forming a **tree** structure.
14+
15+
```cpp
16+
void dfs(int node){
17+
used[node] = true;
18+
for(auto it : g[node])
19+
if(!used[it])
20+
dfs(it);
21+
}
22+
```
23+
24+
### Types of Edges
25+
26+
When traversing a graph using DFS order, several types of edges can be encountered. These edges will be very helpful in understanding some graph algorithms.
27+
28+
**Types of Edges:**
29+
- **Tree edge:** These are the main edges used while traversing the graph.
30+
- **Forward edge:** These edges lead to a node that has been visited before and is located in our own subtree.
31+
- **Back edge:** These edges lead to nodes that have been visited before but where the DFS process is not yet complete.
32+
- **Cross edge:** These edges lead to nodes that have been visited before and where the DFS process is already complete.
33+
34+
An important observation about these edges is that in an undirected graph, it is impossible to have a cross edge. This is because it is not possible for an edge emerging from a node where the DFS process is complete to remain unvisited.
35+
36+
<figure markdown="span" style="width: 36%">
37+
![Green-colored edges are tree edges. Edge (1,8) is a forward edge. Edge (6,4) is a back edge. Edge (5,4) is a cross edge.](img/types-of-edges.png)
38+
<figcaption>Green-colored edges are tree edges. Edge (1,8) is a forward edge. Edge (6,4) is a back edge. Edge (5,4) is a cross edge.</figcaption>
39+
</figure>
40+
41+
## Bridge
42+
43+
In an **undirected** and **connected** graph, if removing an edge causes the graph to become disconnected, this edge is called a **bridge**.
44+
45+
### Finding Bridges
46+
47+
Although there are several algorithms to find bridges (such as **Chain Decomposition**), we will focus on **Tarjan's Algorithm**, which is among the easiest to implement and the fastest.
48+
49+
When traversing a graph using DFS, if there is a **back edge** coming out of the subtree of the lower endpoint of an edge, then that edge is **not** a bridge. This is because the **back edge** prevents the separation of the subtree and its ancestors when the edge is removed.
50+
51+
This algorithm is based exactly on this principle, keeping track of the minimum depth reached by the **back edge**s within the subtree of each node.
52+
53+
If the minimum depth reached by the **back edge**s in the subtree of the lower endpoint of an edge is greater than or equal to the depth of the upper endpoint, then this edge is a **bridge**. This is because no **back edge** in the subtree of the edge's lower endpoint reaches a node above the current edge. Therefore, if we remove this edge, the subtree and its ancestors become disconnected.
54+
55+
Using Tarjan's Algorithm, we can find all bridges in a graph with a time complexity of $\mathcal{O}(V + E)$, where $V$ represents the number of vertices and $E$ represents the number of edges in the graph.
56+
57+
```cpp
58+
int dfs(int node, int parent, int depth) {
59+
int minDepth = depth;
60+
dep[node] = depth; // dep dizisi her dugumun derinligini tutmaktadir.
61+
used[node] = true;
62+
for (auto it : g[node]) {
63+
if (it == parent)
64+
continue;
65+
if (used[it]) {
66+
minDepth = min(minDepth, dep[it]);
67+
// Eger komsu dugum daha once kullanilmis ise
68+
// Bu edge back edge veya forward edgedir.
69+
continue;
70+
}
71+
int val = dfs(it, node, depth + 1);
72+
// val degeri alt agacindan yukari cikan minimum derinliktir.
73+
if (val >= depth + 1)
74+
bridges.push_back({node, it});
75+
minDepth = min(minDepth, val);
76+
}
77+
return minDepth;
78+
}
79+
```
80+
81+
## Articulation Point
82+
83+
In an undirected graph, if removing a node increases the number of connected components, that node is called an **articulation point** or **cut point**.
84+
85+
<figure markdown="span" style="width: 36%">
86+
![For example, if we remove node 0, the remaining nodes are split into two groups: 5 and 1, 2, 3, 4. Similarly, if we remove node 1, the nodes are split into 5, 0 and 2, 3, 4. Therefore, nodes 0 and 1 are **articulation points**.](img/cut-point.png)
87+
<figcaption>For example, if we remove node 0, the remaining nodes are split into two groups: 5 and 1, 2, 3, 4. Similarly, if we remove node 1, the nodes are split into 5, 0 and 2, 3, 4. Therefore, nodes 0 and 1 are **articulation points**.</figcaption>
88+
</figure>
89+
90+
### Finding Articulation Points
91+
92+
Tarjan's Algorithm for finding articulation points in an undirected graph:
93+
94+
- Traverse the graph using DFS order.
95+
96+
- For each node, calculate the depth of the minimum depth node that can be reached from the current node and its subtree through back edges. This value is called the **low** value of the node.
97+
98+
- If the **low** value of any child of a non-root node is greater than or equal to the depth of the current node, then the current node is an **articulation point**. This is because no **back edge** in the subtree of this node can reach a node above the current node. Therefore, if this node is removed, its subtree will become disconnected from its ancestors.
99+
100+
- If the current node is the root (the starting node of the DFS order) and there are multiple branches during the DFS traversal, then the root itself is an **articulation point**. This is because the root has multiple connected subgraphs.
101+
102+
Using Tarjan's Algorithm, we can find all articulation points in a graph with a time complexity of $\mathcal{O}(V + E)$, where $V$ is the number of vertices and $E$ is the number of edges in the graph.
103+
104+
```cpp
105+
int dfs(int node, int parent, int depth) {
106+
int minDepth = depth, children = 0;
107+
dep[node] = depth; // dep array holds depth of each node.
108+
used[node] = true;
109+
for (auto it : g[node]) {
110+
if (it == parent)
111+
continue;
112+
if (used[it]) {
113+
minDepth = min(minDepth, dep[it]);
114+
continue;
115+
}
116+
int val = dfs(it, node, depth + 1);
117+
if (val >= depth and parent != -1)
118+
isCutPoint[node] = true;
119+
minDepth = min(minDepth, val);
120+
children++;
121+
}
122+
// This if represents the root condition that we mentioned above.
123+
if (parent == -1 and children >= 2)
124+
isCutPoint[node] = true;
125+
return minDepth;
126+
}
127+
```

docs/graph/img/biconnectivity.png

21.8 KB
Loading

docs/graph/img/cut-point.png

17.4 KB
Loading

docs/graph/img/first-flow.png

392 KB
Loading

docs/graph/img/flow1.png

22 KB
Loading

docs/graph/img/flow2.png

23.3 KB
Loading

docs/graph/img/flow3.png

22.8 KB
Loading

docs/graph/img/flow4.png

23.5 KB
Loading

docs/graph/img/flow5.png

23.3 KB
Loading

docs/graph/img/scc-graph.png

6.24 KB
Loading

0 commit comments

Comments
 (0)