[알고리즘설계]DFS를 이용한 위상정렬

1 분 소요

[알고리즘설계] DFS를 이용한 위상정렬

코드 리뷰

  • 접점과 간선의 정보를 통해 방향그래프를 만든다.

  • 위상정렬을 하려면 방향그래프에 사이클이 없어야 한다.

  • 한번도 방문하지 않은 정점은 white , 정점에 인접한 정점들을 모두 방문하고 return이 되어 돌아올 경우 black으로, 그리고 아직 인접한 정점들에 대해 dfs가 진행중일 경우 gray로 visit 배열을 채운다.

  • 만약 v의 인접한 정점 w를 방문하였는데, 그 w의 색상이 white일 경우 아직 한번도 방문하지 않은 정점이므로 gray로 바꾼다.

  • v의 인접한 정점 w를 방문하였는데, 그 w의 색상이 gray일 경우, w에서 dfs를 진행하여 온 v가 다시 w를 바라보게 되는 상황이므로 사이클이 존재하는 방향그래프가 되어 위상정렬을 할수 없게 된다. (gray를 바라본 것과 백에지가 그 정점으로 향한 것은 동치)

  • v의 인접한 정점 w를 방문하려는데, 그 w의 색상이 black일 경우, 이미 w는 dfs를 진행하여 후손노드들을 모두 방문하고 return이 된 상황이라 재탐색할 필요가 없으므로, continue 시킨다.

  • 이렇게 모든 정점에 대해 dfs를 진행하고, return이 될 때마 배열에 추가한다음 배열을 역순으로 출력하면, 위상정렬이 완료된다.

#include <iostream>
#include <vector>
using namespace std;

char color[100];
int time;
int discover_time[100];
int finish_time[100];
int V, E;
int ans[100];
int idx;
bool cycle_exist=false;
vector <vector <int>> adj(100);

void DFS(int v) {
	color[v] = 'g'; //gray
	discover_time[v] = ++time;
	int size = adj[v].size();
	for (int i = 0; i < size; i++) {
		int w = adj[v][i];
		if (color[w] == 'w') {//white 만날때
			color[w] = 'g';
			DFS(w);
		}
		if (color[w] == 'g') {//gray 만날때
			cycle_exist = true;
			return;
		}
		if (color[w] == 'b') {//black
			continue;
		}
	}
	finish_time[v] = ++time;
	color[v] = 'b';
	ans[idx++] = v;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> V >> E;
	int a, b;
	for (int i = 0; i < E; i++) {
		cin >> a >> b;
		adj[a].push_back(b); //a->b로
	}
	for (int i = 1; i <= V; i++) {
		color[i] = 'w';//white
	}
	for (int i = 1; i <= V; i++) {
		if (color[i] == 'w') {
			DFS(i);
		}
	}
	if (cycle_exist) cout << "위상정렬 실패(사이클 존재)\n";
	else {
		for (int i = V - 1; i >= 0; i--) cout << ans[i] << " ";
		cout << "\n";
	}
	return 0;
}

댓글남기기