Skip to content

Commit 49acb30

Browse files
committed
Add Strong Orientation
1 parent 0ea5316 commit 49acb30

File tree

2 files changed

+138
-0
lines changed

2 files changed

+138
-0
lines changed

src/graph/strong-orientation.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<!--?title Strong Orientation-->
2+
3+
# Graph Strong Orientation
4+
5+
A **strong orientation** of an undirected graph is an assignment of a direction to each edge that makes it a [strongly connected graph](./graph/strongly-connected-components.html).
6+
That is, after the *orientation* we should be able to visit any vertex from any vertex by following the directed edges.
7+
8+
## Solution
9+
10+
Of course, this cannot be done to *every* graph.
11+
Consider a [bridge](./graph/bridge-searching.html) in a graph.
12+
We have to assign a direction to it and by doing so we make this bridge "crossable" in only one direction. That means we can't go from one of the bridge's ends to the other, so we can't make the graph strongly connected.
13+
14+
Now consider a [DFS](./graph/depth-first-search.html) through a bridgeless connected graph.
15+
Clearly, we will visit each vertex.
16+
And since there are no bridges, we can remove any DFS tree edge and still be able to go
17+
from below the edge to above the edge by using a back edge.
18+
From this follows that from any vertex we can go to the DFS tree root by using back edges.
19+
Then, from the DFS tree root we can visit any vertex we choose.
20+
We found a strong orientation!
21+
22+
In other words, to strongly orient a bridgeless connected graph,
23+
run a DFS on it and let the DFS tree edges point away from the DFS root and
24+
all other edges from the descendant to the ancestor in the DFS tree.
25+
26+
The result that bridgeless connected graphs are exactly the graphs that have strong orientations is called **Robbins' theorem**.
27+
28+
## Problem extension
29+
30+
Let's consider the problem of finding a graph orientation so that the number of SCCs is minimal.
31+
32+
Of course, each graph component can be considered separately.
33+
Now, since only bridgeless graphs are strongly orientable, let's remove all bridges temporarily.
34+
We end up with some number of bridgeless components
35+
(exactly *how many components there were at the beginning* + *how many bridges there were*)
36+
and we know that we can strongly orient each of them.
37+
38+
We were only allowed to orient edges, not remove them, but it turns out we can orient the bridges arbitrarily.
39+
Of course, the easiest way to orient them is to run the algorithm described above without modifications on each original connected component.
40+
41+
### Implementation
42+
43+
Here, the input is *n* — the number of vertices, *m* — the number of edges, then *m* lines describing the edges.
44+
45+
The output is the minimal number of SCCs on the first line and on the second line
46+
a string of *m* characters,
47+
either `>` — telling us that the corresponding edge from the input
48+
is oriented from the left to the right vertex (as in the input),
49+
or `<` — the opposite.
50+
51+
This is a bridge search algorithm modified to also orient the edges,
52+
you can as well orient the edges as a first step and count the SCCs on the oriented graph as a second.
53+
54+
```cpp
55+
#include <cstdio>
56+
#include <vector>
57+
58+
using namespace std;
59+
60+
typedef pair<int, int> pii;
61+
62+
vector<vector<pii>> adj; // adjacency list - pairs (vertex index, edge index)
63+
vector<pii> edges;
64+
65+
vector<int> index, low;
66+
int tmpbridges;
67+
vector<int> orient;
68+
vector<bool> edge_used;
69+
void find_bridges(int v, int pedge = -1) {
70+
static int time = 0;
71+
low[v] = index[v] = time++;
72+
for (auto p : adj[v]) {
73+
if (edge_used[p.second]) continue;
74+
int nv = p.first;
75+
if (index[nv] == -1) { // if nv is not visited yet
76+
edge_used[p.second] = true;
77+
find_bridges(nv, p.second);
78+
orient[p.second] = v != edges[p.second].first;
79+
if (low[nv] < low[v]) {
80+
low[v] = low[nv];
81+
}
82+
if (low[nv] > index[v]) {
83+
// a bridge between v and nv
84+
tmpbridges++;
85+
}
86+
} else if (p.second != pedge) {
87+
edge_used[p.second] = true;
88+
orient[p.second] = v != edges[p.second].first;
89+
if (low[nv] < low[v]) {
90+
low[v] = low[nv];
91+
}
92+
}
93+
}
94+
}
95+
96+
int main() {
97+
int n, m;
98+
scanf("%d %d", &n, &m);
99+
adj.resize(n);
100+
index.resize(n, -1);
101+
low.resize(n, -1);
102+
orient.resize(m);
103+
edges.resize(m);
104+
edge_used.resize(m);
105+
for (int i = 0; i < m; i++) {
106+
int a, b;
107+
scanf("%d %d", &a, &b);
108+
a--; b--;
109+
adj[a].push_back({b, i});
110+
adj[b].push_back({a, i});
111+
edges[i] = {a, b};
112+
}
113+
int result = 0;
114+
for (int v = 0; v < n; v++) {
115+
if (index[v] == -1) {
116+
tmpbridges = 0;
117+
find_bridges(v);
118+
result += tmpbridges+1;
119+
}
120+
}
121+
printf("%d\n", result);
122+
for (int i = 0; i < m; i++) {
123+
if (orient[i] == 0) {
124+
printf(">");
125+
} else {
126+
printf("<");
127+
}
128+
}
129+
puts("");
130+
}
131+
```
132+
133+
134+
135+
## Practice Problems
136+
137+
* [26th Polish OI - Osiedla](https://szkopul.edu.pl/problemset/problem/nldsb4EW1YuZykBlf4lcZL1Y/site/)

src/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ and adding new articles to the collection.*
156156
- [Finding Bridges Online](./graph/bridge-searching-online.html)
157157
- [Finding Articulation Points in O(N+M)](./graph/cutpoints.html)
158158
- [Strongly Connected Components and Condensation Graph](./graph/strongly-connected-components.html)
159+
- [Strong Orientation](./graph/strong-orientation.html)
159160
- **Single-source shortest paths**
160161
- [Dijkstra - finding shortest paths from given vertex](./graph/dijkstra.html)
161162
- [Dijkstra on sparse graphs](./graph/dijkstra_sparse.html)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy