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

1 분 소요

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

코드 리뷰

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

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

  • 또한 방향그래프에 사이클이 없으면 위상정렬을 할 수 있으므로, 둘은 동치관계가 된다.

  • 사이클이 없는 그래프에는 indegree(v)가 0인 vertex v가 항상 존재한다.

  • 즉 모든 vertex에 대해 indegree 개수를 저장한다.

  • indegree가 0인 vertex 들을 queue에 집어넣는다.

  • queue의 맨앞에 있는 접점에 대하여 bfs 탐색을 시작하는데, 기준 접점에서 인접한 다음접점으로 이어지는 간선을 뺀 나머지 indegree개수가 0인 경우, queue에 집어넣는다.

  • queue에서 pop되는 순서대로 출력하면 위상정렬이 완성된다.

  • 사이클이 있는 방향그래프에선 bfs를 진행하다보면, indegree가 0인 접점이 더이상 존재하지 않는 경우가 생기므로, 그런 경우 위상정렬 불가능.

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

int V, E;
int check[500];
int indegree[500];
int ans[500];
vector <vector <int>> adj(500);
queue <int> q;

void bfs() {
	int idx = 0;
	while (!q.empty()) {
		int now = q.front();
		check[now] = 1;
		ans[idx++] = now;
		q.pop();
		int size = adj[now].size();
		for (int i = 0; i < size; i++) {
			int next = adj[now][i];
			indegree[next]--;
			if (indegree[next] == 0) q.push(next);
		}
	}
}

int main() {
	int a, b;
	printf("접점의 개수: ");
	scanf("%d", &V);
	printf("간선의 개수: ");
	scanf("%d", &E);
	for (int i = 0; i < E; i++) {
		scanf("%d %d", &a, &b); //a -> b로 이어지게 방향그래프 만듬
		adj[a].push_back(b);
		indegree[b]++;
	}
	for (int i = 1; i <= V; i++) {
		if (indegree[i] == 0) {
			q.push(i);
		}
	}
	bfs();
	if (ans[V - 1] == 0) {
		printf("사이클이 있는 방향그래프\n");
		return 0;
	}
	for (int i = 0; i < V; i++) {
		printf("%d ", ans[i]);
	}
	return 0;
}

댓글남기기