强连通分量的C++代码实现与讲解
以下是强连通分量的C++代码实现以及过程讲解:
假设我们有一个有向图,我们需要找到它的所有强连通分量。
步骤1:首先,我们需要定义一个全局变量用于记录强连通分量的数量。我们可以称之为SCC_COUNT,并将其初始化为0。
int SCC_COUNT = 0;
步骤2:接下来,我们需要定义一个DFS函数,该函数将用于处理每个节点,并查找其所属的强连通分量。该函数的参数包括当前节点的编号,图的邻接表,一个布尔类型的visited数组以记录节点是否已被访问以及一个stack
void DFS(int u, vector
visited[u] = true;
for (int v : adj[u]) {
if (!visited[v]) {
DFS(v, adj, visited, st);
}
}
st.push(u);
}
步骤3:我们接着需要定义一个逆DFS函数,该函数将用于遍历图的逆图,并以相反的遍历顺序查找每个节点的强连通分量。该函数的参数包括当前节点的编号,图的逆邻接表,一个布尔类型的visited数组以记录节点是否已被访问以及一个vector
void reverseDFS(int u, vector
visited[u] = true;
component.push_back(u);
for (int v : revAdj[u]) {
if (!visited[v])
reverseDFS(v, revAdj, visited, component);
}
}
步骤4:我们现在可以处理我们的强连通分量算法了。将所有节点标记为未访问状态,然后对于每个未访问的节点,我们使用DFS函数进行完整的DFS遍历,并在每次访问节点时将其推到stack中。这样,我们可以确定遍历顺序,并得到一个stack,其中顶部元素表示末尾节点。然后,我们遍历每个节点并反向遍历逆邻接列表,以找到其所属的强连通分量。对于每个节点,我们标记它是否已访问,以防止重复计算。同时,我们使用vector数组来存储组件中的所有节点。在reverseDFS递归完成后,我们会得到一个组件,该组件包含属于该强连通分量的所有节点。我们将增加SCC_COUNT,并将这些节点添加到我们的结果向量中。
vector<vector
bool visited[N];
memset(visited, 0, sizeof(visited));
stack<int> st;
for (int i = 0; i < N; i++) {
if (!visited[i]) {
DFS(i, adj, visited, st);
}
}
SCC_COUNT = 0;
vector<vector<int>> scc;
memset(visited, 0, sizeof(visited));
while (!st.empty()) {
int u = st.top();
st.pop();
if (!visited[u]) {
vector<int> component;
reverseDFS(u, revAdj, visited, component);
scc.push_back(component);
SCC_COUNT++;
}
}
return scc;
}
完整C++代码实现:
include <bits/stdc++.h>
define endl '\n'
using namespace std;
const int N = 100005;
vector
int SCC_COUNT = 0;
void DFS(int u, vector
visited[u] = true;
for (int v : adj[u]) {
if (!visited[v]) {
DFS(v, adj, visited, st);
}
}
st.push(u);
}
void reverseDFS(int u, vector
visited[u] = true;
component.push_back(u);
for (int v : revAdj[u]) {
if (!visited[v])
reverseDFS(v, revAdj, visited, component);
}
}
vector<vector
bool visited[N];
memset(visited, 0, sizeof(visited));
stack<int> st;
for (int i = 0; i < N; i++) {
if (!visited[i]) {
DFS(i, adj, visited, st);
}
}
SCC_COUNT = 0;
vector<vector<int> > scc;
memset(visited, 0, sizeof(visited));
while (!st.empty()) {
int u = st.top();
st.pop();
if (!visited[u]) {
vector<int> component;
reverseDFS(u, revAdj, visited, component);
scc.push_back(component);
SCC_COUNT++;
}
}
return scc;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, m;
cin >> n >> m;
for (int i = 0; i < m; i++) {
int x, y;
cin >> x >> y;
adj[x].push_back(y);
revAdj[y].push_back(x);
}
vector<vector<int> > scc = getStronglyConnectedComponents(adj, revAdj, n);
cout << "Number of Strongly Connected Components: " << SCC_COUNT << endl;
cout << "Strongly Connected Components: " << endl;
for (vector<int>& component : scc) {
for (int& node : component) {
cout << node << " ";
}
cout << endl;
}
return 0;
}