강한 연결 요소(Strongly Connected Component, SCC)
Updated:
Categories: Algorithm Theory
SCC는 강하게 결합된 정점 집합을 의미한다.
즉, SCC의 임의의 u와 v는 u→v , v→u 모두 가능하다는 뜻이다.
사이클이 발생하면 무조건 SCC에 해당되는 특징이 있다.
시간복잡도 : O(V+E)
![[assets/images/posts_img/Untitled 6.png | Untitled 6.png]] |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
class SCC {
private:
int N, _id, _scc;
vector<int> id, scc, cnt, dp; //scc[x] := x번 노드의 scc 번호, cnt[scc_x] := scc_x번의 scc의 집합 크기, dp[x] := src->x 의 최대 개수(bfs)
vector<vector<int>> g, scc_g;
stack<int> st;
int dfs(int u) {
id[u] = _id++;
st.push(u);
int parent = id[u];
for(int v : g[u]) {
if(id[v] == -1) parent = min(parent, dfs(v));
else if(scc[v] == -1) parent = min(parent, id[v]);
}
if(parent == id[u]) {
while(true) {
int t = st.top(); st.pop();
scc[t] = _scc;
cnt[_scc]++;
if(t == u) break;
}
_scc++;
}
return parent;
}
int bfs(int src, int sink) {
dp = vector<int>(_scc, 0);
queue<int> q;
q.push(src); dp[src] = cnt[src];
while(!q.empty()) {
int here = q.front(); q.pop();
for(int there : scc_g[here]) {
if(dp[there] >= dp[here] + cnt[there]) continue;
dp[there] = dp[here] + cnt[there];
q.push(there);
}
}
return dp[sink];
}
public:
SCC(int _N) : N(_N), _id(1), _scc(1), id(N+1, -1), scc(N+1, -1), cnt(N+1,0), g(N+1) {}
void add_edge(int u, int v) { g[u].emplace_back(v); }
void find_scc() {
for(int i=1; i<=N; i++)
if(id[i] == -1) dfs(i);
scc_g.resize(_scc);
for(int u=1; u<=N; u++) {
for(int v : g[u]) {
if(scc[u] != scc[v]) scc_g[scc[u]].emplace_back(scc[v]);
}
}
}
int solve(int S, int T) {
return bfs(scc[S], scc[T]);
}
};
Leave a comment