일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 스프링 부트
- 골드4
- EC2
- 디자인패턴
- 카카오테크 부트캠프
- 골드3
- 정보처리기사
- ETRI
- aws
- 엘라스틱빈스톡
- Express
- 백준 알고리즘
- express.js
- 코딩테스트 고득점 kit
- 스프링부트
- 골드5
- 한국전자통신연구원
- 자바
- 도커
- 배포
- 자료구조
- DP
- 인스턴스
- 대전
- DFS
- 정처기
- 프로그래머스
- 알고리즘
- BFS
- 카테부
Archives
JUINTINATION
위상정렬(Topological Sort) 본문
반응형
위상정렬(Topological Sort)이란?
- 유향 비순환 그래프(DAG, Directed Acyclic Graph)에서 정점을 간선의 방향을 거스르지 않도록 나열하는 알고리즘이다.
- 다음 라면 끓이기 예제를 보자
우리는 라면을 끓일 때 냄비에 물을 먼저 부어도 되고 라면 봉지를 먼저 뜯어도 되지만 계란은 맨 마지막에 풀어야 한다.
이러한 방향은 있지만 사이클은 없는 그래프를 간선의 방향을 거스르지 않고 한 줄로 정렬시키는 것이 위상정렬이라고 보면 될 것 같다.
위상정렬 알고리즘(1)
- 진입 간선이 없는 정점을 연결리스트 R의 맨 뒤에 연결하고 해당 정점과 그 정점의 진출 간선을 제거하는 과정을 반복한다.
- 의사 코드는 다음과 같으며 위의 예시를 구하는 과정은 그 다음 그림과 같다.
topological_sort1(G) {
for i ← 1 to n {
/* 진입 간선이 없는 정점 u 선택 */
/* 연결리스트 R의 맨 뒤에 u 삽입 */
/* 정점 u와 u의 진출 간선 제거 */
}
}
위상정렬 알고리즘(2)
- 깊이 우선 탐색을 기반으로 탐색중인 정점을 순서대로 연결리스트 R의 맨 앞에 연결하는 과정을 반복한다.
- 의사 코드는 다음과 같으며 위의 예시를 구하는 과정은 그 다음 그림과 같다.
topological_sort2(G, V) {
for each v ∈ V {
visited[v] ← false;
}
for each v ∈ V {
if visited[v] = false
then dfs_tf(v);
}
}
dfs_ts(v) {
visited[v] = true;
for each x ∈ adj[v] {
if visited[x] = false
then dfs_ts(x);
}
/* 연결리스트 R의 맨 앞에 v 삽입 */
}
이해를 돕기 위해 백준 문제를 첨부한다.
https://www.acmicpc.net/problem/2252
2252번: 줄 세우기
첫째 줄에 N(1 ≤ N ≤ 32,000), M(1 ≤ M ≤ 100,000)이 주어진다. M은 키를 비교한 회수이다. 다음 M개의 줄에는 키를 비교한 두 학생의 번호 A, B가 주어진다. 이는 학생 A가 학생 B의 앞에 서야 한다는 의
www.acmicpc.net
위상정렬 알고리즘(1)을 이용한 풀이
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.ArrayList;
import java.util.Queue;
import java.util.LinkedList;
public class Main {
static int[] inDegree;
static ArrayList<Integer>[] edges;
public static String topologySort() {
Queue<Integer> queue = new LinkedList<>();
for (int i = 1; i < inDegree.length; i++) {
if (inDegree[i] == 0) {
queue.offer(i);
}
}
StringBuilder sb = new StringBuilder();
for (int i = 1; i < inDegree.length; i++) {
int p = queue.poll();
sb.append(p).append(" ");
for (int e : edges[p]) {
if (--inDegree[e] == 0) {
queue.offer(e);
}
}
}
return sb.toString();
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
edges = new ArrayList[n + 1];
inDegree = new int[n + 1];
for (int i = 1; i <= n; i++) {
edges[i] = new ArrayList<Integer>();
}
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine(), " ");
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
edges[a].add(b);
inDegree[b]++;
}
System.out.println(topologySort());
}
}
위상정렬 알고리즘(2)를 이용한 풀이
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Stack;
public class Main {
static Stack<Integer> stack = new Stack<>();
static ArrayList<Integer>[] edges;
static boolean[] visited;
public static String topologySort(int n) {
Arrays.fill(visited, false);
for (int i = 1; i <= n; i++) {
if (!visited[i]) {
dfs_ts(i);
}
}
StringBuilder sb = new StringBuilder();
while (!stack.isEmpty()) {
sb.append(stack.pop()).append(" ");
}
return sb.toString();
}
public static void dfs_ts(int v) {
visited[v] = true;
for (int x : edges[v]) {
if (!visited[x]) {
dfs_ts(x);
}
}
stack.push(v);
}
@SuppressWarnings("unchecked")
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
edges = new ArrayList[n + 1];
visited = new boolean[n + 1];
for (int i = 1; i <= n; i++) {
edges[i] = new ArrayList<Integer>();
}
for (int i = 0; i < m; i++) {
st = new StringTokenizer(br.readLine(), " ");
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
edges[a].add(b);
}
System.out.println(topologySort(n));
}
}
반응형
'자료구조 및 알고리즘' 카테고리의 다른 글
APSP(All-pairs shortest paths) (0) | 2023.08.08 |
---|---|
SSSP(Single-source shortest paths) (0) | 2023.08.06 |
최소 신장 트리(Minimum Spanning Tree) (1) | 2023.07.31 |
해시 테이블(Hash Table) (0) | 2023.07.24 |
유니온 파인드(Union-Find) (0) | 2023.07.23 |
Comments