record logo record

강한 연결 요소(Strongly Connected Component)란?

강한 연결 요소(Strongly Connected Component) 알고리즘의 특징

강한 연결 요소(Strongly Connected Component)의 알고리즘 예시

강한 연결 요소(SCC) 는 그 자체로는 큰 의미가 없고, 위상 정렬 과 함께 생각해 보았을 때 큰 의미가 있다.
모든 SCC를 각 정점으로 고려했을 때 각 SCC를 위상 정렬할 수 있다.

Source Code

#include <iostream>
#include <vector>
#include <stack>
#define MAX 10001

using namespace std;

int id, d[MAX];// 각 아이디마다 고유한 노드 저장. 
bool finished[MAX];// 특정 노드에 대한 DFS가 끝났는지 확인하는것. 
vector<int> a[MAX]; // 실질적으로 인접한 노드를 저장 
vector<vector<int> > SCC; // 한 그래프에서 여러개 나올 수 있기때문에  
stack<int> s;

// DFS는 총 정점의 갯수만큼 실행된다.
int dfs(int x){
	d[x] = ++id;
	s.push(x); // 스택에 자기 자신을 삽입한다.
	
	int parent = d[x];
	for(int i = 0; i < a[x].size(); i++) {
		int y = a[x][i];
		// 방문하지 않은 이웃 
		if(d[y] == 0) parent = min(parent, dfs(y));
		// 처리 중인 이웃 
		else if(!finished[y]) parent = min(parent, d[y]);
		
	}
	
	// 부모노드가 자기 자신인 경우
	if(parent == d[x]) {
		vector<int> scc;
		while(1){
			int t = s.top();
			s.pop();
			scc.push_back(t);
			finished[t] = true;
			if(t == x) break;
		}
		SCC.push_back(scc);
	} 
	return parent;
} 

int main(void) {
	int v = 11;
	a[1].push_back(2);
	a[2].push_back(3);
	a[3].push_back(1);
	a[4].push_back(2);
	a[4].push_back(5);
	a[5].push_back(7);
	a[6].push_back(5);
	a[7].push_back(6);
	a[8].push_back(5);
	a[8].push_back(9);
	a[9].push_back(10);
	a[10].push_back(11);
	a[11].push_back(3);
	a[11].push_back(8);
	
	for(int i = 1; i <= v; i++) {
		if(d[i] == 0) dfs(i);
	}
	printf("SCC의 개수: %d\n", SCC.size());
	for(int i = 0; i < SCC.size(); i++) {
	printf("%d 번째 SCC : ", i + 1);
		for(int j = 0; j < SCC[i].size(); j++) {
			printf("%d ", SCC[i][j]);
		}
		printf("\n");
	}
	return 0;
}

강한 연결 요소(Strongly Connected Component)의 시간복잡도

강한 연결 요소(Strongly Connected Component)

시간 복잡도는 O(V + E) 이다. 또한, 타잔 알고리즘의 시간 복잡도는 O(V + E)로 위상 정렬 의 시간 복잡도와 동일하다.

관련된 Post

References