๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด

Topological Sort (์œ„์ƒ ์ •๋ ฌ)

Topological sort๋Š” Direct Acyclic Graph ์˜ ๊ฒฝ์šฐ์—์„œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๋ฐฉํ–ฅ์ด ์กด์žฌํ•˜๋Š” ๊ทธ๋ž˜ํ”„์—์„œ ๊ฐ vertex์˜ ์„ ํ–‰ ์ˆœ์„œ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•˜๋ฉด์„œ ๋ชจ๋“  vertex๋ฅผ ํƒ์ƒ‰ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค.

Type of Edges

์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์•Œ์•„๋ณด๊ธฐ ์ „์—, Direct Acyclic Graph๋ฅผ ์•Œ๊ธฐ ์œ„ํ•ด ๋ฐฉํ–ฅ์ด ์žˆ๋Š” ๊ทธ๋ž˜ํ”„์—์„œ DFS๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ๋‚˜ํƒ€๋‚˜๋Š” edge์˜ ์ข…๋ฅ˜๋ฅผ ๋จผ์ € ์ •๋ฆฌํ•ด๋ณด์ž.

  1. Tree Edge: ์ƒˆ๋กœ์šด ์ •์ ์„ ๋งŒ๋‚ฌ์„ ๋•Œ ์ƒ๊ธฐ๋Š” edge. Edge๋Š” ํ•œ ์ •์ ์—์„œ ๋‹ค๋ฅธ ์ •์ ์„ ์ด์„ ๋•Œ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค. Tree Edge๋Š” ์–ด๋–ค ์ •์ ์ด ์ƒˆ๋กœ์šด ์ •์ ๊ณผ ์—ฐ๊ฒฐ ๋  ๋•Œ ์ƒ๊ธฐ๋Š” edge๋ฅผ ๋งํ•œ๋‹ค.

  1. Back Edge: Back Edge๋Š” ํŠธ๋ฆฌ์—์„œ ์ž์†์— ์œ„์น˜ํ•œ ๋…ธ๋“œ๊ฐ€ ์กฐ์ƒ ๋…ธ๋“œ์™€ ์ด์–ด์ง€๋Š” edge๋ฅผ ๋งํ•œ๋‹ค.

  1. Forward Edge: Forward Edge๋Š” ์กฐ์ƒ ๋…ธ๋“œ๊ฐ€ ์ž์† ๋…ธ๋“œ์™€ ์ด์–ด์ง€๋Š” edge๋ฅผ ๋งํ•œ๋‹ค.

  1. Cross Edge: ํ˜„์žฌ ํƒ์ƒ‰์ค‘์ธ ํŠธ๋ฆฌ๊ฐ€ ๋‹ค๋ฅธ ํƒ์ƒ‰์ด ๋๋‚œ ๋‹ค๋ฅธ ์„œ๋ธŒํŠธ๋ฆฌ์™€ ์ด์–ด์ง€๋Š” ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•˜๋Š” edge๋ฅผ ๋งํ•œ๋‹ค.

Edges in Undirected

Directed Acyclic Graph ์—์„œ๋Š”, ์œ„ ๋„ค ๊ฐœ์˜ edge ์ค‘ ์กด์žฌํ•  ์ˆ˜ ์—†๋Š” edge๋“ค์ด ์žˆ๋‹ค.

  1. Foward Edge : ์šฐ๋ฆฌ๋Š” forward edge๊ฐ€ ์กฐ์ƒ ๋…ธ๋“œ์™€ ์ž์† ๋…ธ๋“œ๊ฐ€ ์ด์–ด์ง€๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ •์˜ํ–ˆ๋‹ค. ์ด ์ƒํ™ฉ์—์„œ ์ž์† ๋…ธ๋“œ๋Š” ํ˜„์žฌ ํƒ์ƒ‰ ์ค‘์ธ ๋…ธ๋“œ์—ฌ์•ผ ํ•˜๋Š”๋ฐ, ํ˜„์žฌ ํƒ์ƒ‰์ค‘์ธ ๋…ธ๋“œ๊ฐ€ ๊ทธ ์กฐ์ƒ ๋…ธ๋“œ์™€ ์—ฐ๊ฒฐ๋˜๋Š” ๊ฒƒ์€ ๋ถˆ๊ฐ€๋Šฅ ํ•˜๋‹ค. ์ž์† ๋…ธ๋“œ์— ๋„๋‹ฌ ํ–ˆ๋‹ค๋Š” ๊ฒƒ์€ ์ด๋ฏธ ์กฐ์ƒ ๋…ธ๋“œ๊ฐ€ ํƒ์ƒ‰ ์ค‘ ์ƒํƒœ์ธ gray ์ƒํƒœ์ธ ๊ฒƒ์„ ์˜๋ฏธํ•˜๊ณ , gray ์—์„œ gray ๋กœ์˜ ์—ฐ๊ฒฐ์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
  2. Cross Edge : ๋งŒ์•ฝ ์–ด๋–ค ๋‘ ์„œ๋ธŒํŠธ๋ฆฌ๊ฐ€ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๋‹ค๊ณ  ํ•˜์ž. ๊ทธ๋ ‡๋‹ค๋ฉด dfs์—์„œ ํ•œ ์„œ๋ธŒํŠธ๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•˜๋ฉด์„œ ๋ฐ˜๋Œ€ํŽธ์— ์œ„์น˜ํ•œ ์„œ๋ธŒํŠธ๋ฆฌ๊นŒ์ง€ ํ•จ๊ป˜ ํƒ์ƒ‰ํ•  ์ˆ˜ ๋ฐ–์— ์—†๋‹ค. ์™œ๋ƒํ•˜๋ฉด dfs๋Š” ๋” ์ด์ƒ ์ง„ํ–‰ํ•  ์ž๋…€ ๋…ธ๋“œ๊ฐ€ ์—†์„ ๋•Œ๊นŒ์ง€ ๊ณ„์†ํ•ด์„œ ๊ทธ๋ž˜ํ”„๋ฅผ ํƒ€๊ณ  ๊ฐ€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๋”ฐ๋ผ์„œ ๋ฐฉํ–ฅ์ด ์—†๋Š” ๊ทธ๋ž˜ํ”„์—์„œ ์กด์žฌํ•˜๋Š” edge๋Š” Back Edge ์™€ Tree Edge ๋ฟ์ด๋‹ค.

Alogorithm

์œ„์ƒ ์ •๋ ฌ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.

  1. DFS ํ†ตํ•ด ๊ทธ๋ž˜ํ”„์— ์†ํ•œ ๋ชจ๋“  ๋…ธ๋“œ๋“ค์˜ finish time์„ ๋งˆํ‚นํ•œ๋‹ค. ๐›ฉ(V + E)
  2. ๊ฐ€์žฅ ๋Šฆ๊ฒŒ ๋๋‚œ ๋…ธ๋“œ๋ฅผ ๋งํฌ๋“œ ๋ฆฌ์ŠคํŠธ ์ œ์ผ ์•ž์— ์œ„์น˜์‹œํ‚จ๋‹ค. ๐›ฉ(V)

์ •๋ง ๋‹จ์ˆœํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด๋‹ค. ๊ทธ๋ž˜ํ”„ vertex์˜ ์ˆœ์„œ๋Š” ์ด๋ฏธ edge์˜ ๋ฐฉํ–ฅ์— ์˜ํ•ด ์ •๋ฆฌ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์šฐ๋ฆฌ๋Š” ๊ทธ๋ƒฅ dfs๋กœ ๋ชจ๋“  vertex๋ฅผ ํƒ์ƒ‰ํ•ด์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” DFS์˜ ์‹œ๊ฐ„์ธ ๐›ฉ(V+E) ๊ฐ€ ๋œ๋‹ค.

Example

๋ฐฑ์ค€์— ์žˆ๋Š” ์œ„์ƒ์ •๋ ฌ์„ ์‚ฌ์šฉํ•ด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ํ’€์–ด๋ณด์ž.

๋ฌธ์ œ

N๋ช…์˜ ํ•™์ƒ๋“ค์„ ํ‚ค ์ˆœ์„œ๋Œ€๋กœ ์ค„์„ ์„ธ์šฐ๋ ค๊ณ  ํ•œ๋‹ค. ๊ฐ ํ•™์ƒ์˜ ํ‚ค๋ฅผ ์ง์ ‘ ์žฌ์„œ ์ •๋ ฌํ•˜๋ฉด ๊ฐ„๋‹จํ•˜๊ฒ ์ง€๋งŒ, ๋งˆ๋•…ํ•œ ๋ฐฉ๋ฒ•์ด ์—†์–ด์„œ ๋‘ ํ•™์ƒ์˜ ํ‚ค๋ฅผ ๋น„๊ตํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๊ธฐ๋กœ ํ•˜์˜€๋‹ค. ๊ทธ๋‚˜๋งˆ๋„ ๋ชจ๋“  ํ•™์ƒ๋“ค์„ ๋‹ค ๋น„๊ตํ•ด ๋ณธ ๊ฒƒ์ด ์•„๋‹ˆ๊ณ , ์ผ๋ถ€ ํ•™์ƒ๋“ค์˜ ํ‚ค๋งŒ์„ ๋น„๊ตํ•ด ๋ณด์•˜๋‹ค.

์ผ๋ถ€ ํ•™์ƒ๋“ค์˜ ํ‚ค๋ฅผ ๋น„๊ตํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ฃผ์–ด์กŒ์„ ๋•Œ, ์ค„์„ ์„ธ์šฐ๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•˜์‹œ์˜ค.

์ž…๋ ฅ

์ฒซ์งธ ์ค„์— N(1≤N≤32,000), M(1≤M≤100,000)์ด ์ฃผ์–ด์ง„๋‹ค. M์€ ํ‚ค๋ฅผ ๋น„๊ตํ•œ ํšŒ์ˆ˜์ด๋‹ค. ๋‹ค์Œ M๊ฐœ์˜ ์ค„์—๋Š” ํ‚ค๋ฅผ ๋น„๊ตํ•œ ๋‘ ํ•™์ƒ์˜ ๋ฒˆํ˜ธ A, B๊ฐ€ ์ฃผ์–ด์ง„๋‹ค. ์ด๋Š” ํ•™์ƒ A๊ฐ€ ํ•™์ƒ B์˜ ์•ž์— ์„œ์•ผ ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

ํ•™์ƒ๋“ค์˜ ๋ฒˆํ˜ธ๋Š” 1๋ฒˆ๋ถ€ํ„ฐ N๋ฒˆ์ด๋‹ค.

์ถœ๋ ฅ

์ฒซ์งธ ์ค„๋ถ€ํ„ฐ ์•ž์—์„œ๋ถ€ํ„ฐ ์ค„์„ ์„ธ์šด ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค. ๋‹ต์ด ์—ฌ๋Ÿฌ ๊ฐ€์ง€์ธ ๊ฒฝ์šฐ์—๋Š” ์•„๋ฌด๊ฑฐ๋‚˜ ์ถœ๋ ฅํ•œ๋‹ค.

ํ’€์ด

Topological Sort, ์œ„์ƒ ์ •๋ ฌ๋กœ ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์ด๋‹ค. ์œ„์ƒ ์ •๋ ฌ์€ DFS์—์„œ ๊ฐ ๋…ธ๋“œ์˜ ํƒ์ƒ‰์ด ์™„์ „ํžˆ ๋๋‚  ๋•Œ ๊ทธ ์ˆœ์„œ๋ฅผ ๊ธฐ๋กํ•ด๋‘๊ณ  ์ตœ์ข…์ ์œผ๋กœ๋Š” ๊ทธ ์—ญ์ˆœ์œผ๋กœ ์ถœ๋ ฅํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ์œ„์ƒ ์ •๋ ฌ์€ DAG(Directed Acyclic Graph), ์‚ฌ์ดํด์ด ์—†๋Š” ์ผ๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„์—์„œ๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค. DFS๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด์„œ ํƒ์ƒ‰์ด ๋๋‚  ๋•Œ๋งˆ๋‹ค ์Šคํƒ์— ํ•ด๋‹น ๊ฐ’์„ ๋„ฃ์–ด์ฃผ๊ณ , ์ค‘๋ณต๋œ ๋…ธ๋“œ๋ฅผ ์—ฐ์†์œผ๋กœ ํƒ์ƒ‰ํ•˜์ง€ ์•Š๋„๋ก visited ๋งˆํ‚น์„ ํ•ด์ค€๋‹ค.

์ฝ”๋“œ

#include <cstdio>
#include <vector>
#include <stack>
#include <utility>
#include <algorithm>

using namespace std;

vector<vector<int>> adj (32001);
stack<int> lineup;
bool visited[32001];

void dfs (int s){
    visited[s] = true;

    for (int i = 0 ; i < adj[s].size() ; i++){
        if (!visited[adj[s][i]]){
            dfs(adj[s][i]);
        }
    }
    lineup.push(s);
}

int main (){
    int N, M;
    scanf("%d %d", &N, &M);

    for (int i = 0 ; i < M ; i++){
        int a, b;
        scanf("%d %d", &a, &b);
        adj[a].push_back(b);
    }

    for (int i = 1 ; i <= N ; i++){
        if (!visited[i]){
            dfs(i);
        }
    }

    while(!lineup.empty()){
        printf("%d ", lineup.top());
        lineup.pop();
    }
}