코딩뚠뚠

[기본문제풀이] 강한결합요소 본문

알고리즘 문제풀이/기본문제풀이

[기본문제풀이] 강한결합요소

로디네로 2020. 12. 28. 00:50
반응형

 

풀이 일시 : 2020-08-17

강한결합요소 :

strongly connected component SCC로 부르기도 한다.

같은 SCC에 속하는 두 정점은 서로 도달이 가능하다.

문제 :

SCC의 갯수와 각 SCC에 담긴 인자들을 출력하라

풀이 :

모든 정점에 대해 DFS를 수행해서 SCC를 찾는 알고리즘으로 풀이한다.

1->2->3->4 에서 다시 1로 돌아갈 수 있어야 SCC가 성립하는 것.

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>
#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;

int dfs(int x) {
	d[x] = ++id; //노드마다 고유한 번호를 할당 / 방문표시, 다시 dfs실행안하기위함
	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)); //해당노드를 방문한적없다면 해당노드로 dfs를 수행하여 더 작은값으로 부모값갱신
		//처리되지 않은 이웃
		else if (!finished[y]) parent = min(parent, d[y]); //방문은했지만 처리가안됐으면 (dfs수행노드) 더 작은값으로
	}
	if (parent == d[x]) { //부모노드가 자기자신인 경우
		vector<int> scc; //스택에서 꺼내면서 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() {
	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); //각 정점에 대해 한번씩 dfs실행
	}

	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;
}
반응형