😎 κ³΅λΆ€ν•˜λŠ” μ§•μ§•μ•ŒνŒŒμΉ΄λŠ” μ²˜μŒμ΄μ§€?

[이것이 μ½”λ”© ν…ŒμŠ€νŠΈλ‹€ with Python]_ 36_μœ„μƒ μ •λ ¬ λ³Έλ¬Έ

πŸ¦₯ μ½”ν…Œ/이것이 μ½”λ”© ν…ŒμŠ€νŠΈλ‹€ with python

[이것이 μ½”λ”© ν…ŒμŠ€νŠΈλ‹€ with Python]_ 36_μœ„μƒ μ •λ ¬

μ§•μ§•μ•ŒνŒŒμΉ΄ 2022. 2. 13. 00:45
728x90
λ°˜μ‘ν˜•

220213 μž‘μ„±

<λ³Έ λΈ”λ‘œκ·ΈλŠ” γ€Žμ΄κ²ƒμ΄ 취업을 μœ„ν•œ μ½”λ”© ν…ŒμŠ€νŠΈλ‹€γ€ μ˜ youtubeλ₯Ό μ°Έκ³ ν•΄μ„œ κ³΅λΆ€ν•˜λ©° μž‘μ„±ν•˜μ˜€μŠ΅λ‹ˆλ‹€>

https://www.youtube.com/watch?v=xeSz3pROPS8&list=PLVsNizTWUw7H9_of5YCB0FmsSc-K44y81&index=36 

 

 

 

 

 

 

1. μœ„μƒ μ •λ ¬

: 사이클이 μ—†λŠ” λ°©ν–₯ κ·Έλž˜ν”„μ˜ λͺ¨λ“  λ…Έλ“œλ₯Ό λ°©ν–₯성에 거슀λ₯΄μ§€ μ•Šλ„λ‘ μˆœμ„œλŒ€λ‘œ λ‚˜μ—΄ν•˜λŠ” 것

 

 

 

 

2. μ§„μž…μ°¨μˆ˜, μ§„μΆœμ°¨μˆ˜

- μ§„μž…μ°¨μˆ˜ (Indegree) : νŠΉμ •ν•œ λ…Έλ“œλ‘œ λ“€μ–΄μ˜€λŠ” κ°„μ„ μ˜ 개수

- μ§„μΆœμ°¨μˆ˜ (Outdegree) : νŠΉμ • λ…Έλ“œμ—μ„œ λ‚˜κ°€λŠ” κ°„μ„ μ˜ 개수

 

 

 

 

3. μœ„μƒ μ •λ ¬ μ•Œκ³ λ¦¬μ¦˜ + 큐 이용

1) μ§„μž…μ°¨μˆ˜κ°€ 0인 λͺ¨λ“  λ…Έλ“œμ— 큐λ₯Ό λ„£λŠ”λ‹€

2) 큐가 빌 λ•ŒκΉŒμ§€ λ‹€μŒμ˜ κ³Όμ • 반볡

- νμ—μ„œ μ›μ†Œλ₯Ό κΊΌλ‚΄ ν•΄λ‹Ή λ…Έλ“œμ—μ„œ λ‚˜κ°€λŠ” 간선을 κ·Έλž˜ν”„μ—μ„œ 제거

- μƒˆλ‘­κ²Œ μ§„μž…μ°¨μˆ˜κ°€ 0이 된 λ…Έλ“œλ₯Ό 큐에 λ„£λŠ”λ‹€

 

=> 각 λ…Έλ“œκ°€ 큐에 λ“€μ–΄μ˜¨ μˆœμ„œκ°€ μœ„μƒ 정렬을 μˆ˜ν–‰ν•œ 결과와 κ°™λ‹€

 

: DAG (Direct Acyclic Graph) (μˆœν™˜ν•˜μ§€ μ•ŠλŠ” λ°©ν–₯ κ·Έλž˜ν”„) μ—μ„œλ§Œ μˆ˜ν–‰

: 큐에 μƒˆλ‘­κ²Œ λ“€μ–΄κ°€λŠ” μ›μ†Œκ°€ 2개 이상이라면 μ—¬λŸ¬κ°€μ§€ λ‹΅ 쑴재

: λͺ¨λ“  μ›μ†Œλ₯Ό λ°©λ¬Έν•˜κΈ° 전에 큐가 λΉˆλ‹€λ©΄, 사이클이 μ‘΄μž¬ν•œλ‹€!

( 사이클에 ν¬ν•¨λœ μ›μ†Œ μ€‘μ—μ„œ μ–΄λ– ν•œ μ›μ†Œλ„ 큐에 듀어가지 X )

: μŠ€νƒμ„ ν™œμš©ν•œ DFS μ΄μš©ν•΄ μœ„μƒ μ •λ ¬ μˆ˜ν–‰

 

 

 

 

 

  • python
from collections import deque

# λ…Έλ“œμ˜ κ°œμˆ˜μ™€ κ°„μ„ μ˜ 개수λ₯Ό μž…λ ₯ λ°›κΈ°
v, e = map(int, input().split())
# λͺ¨λ“  λ…Έλ“œμ— λŒ€ν•œ μ§„μž…μ°¨μˆ˜λŠ” 0으둜 μ΄ˆκΈ°ν™”
indegree = [0] * (v + 1)
# 각 λ…Έλ“œμ— μ—°κ²°λœ κ°„μ„  정보λ₯Ό λ‹΄κΈ° μœ„ν•œ μ—°κ²° 리슀트 μ΄ˆκΈ°ν™”
graph = [[] for i in range(v + 1)]

# λ°©ν–₯ κ·Έλž˜ν”„μ˜ λͺ¨λ“  κ°„μ„  정보λ₯Ό μž…λ ₯ λ°›κΈ°
for _ in range(e):
    a, b = map(int, input().split())
    graph[a].append(b) # 정점 Aμ—μ„œ B둜 이동 κ°€λŠ₯
    # μ§„μž… 차수λ₯Ό 1 증가
    indegree[b] += 1

# μœ„μƒ μ •λ ¬ ν•¨μˆ˜
def topology_sort():
    result = [] # μ•Œκ³ λ¦¬μ¦˜ μˆ˜ν–‰ κ²°κ³Όλ₯Ό 담을 리슀트
    q = deque() # 큐 κΈ°λŠ₯을 μœ„ν•œ deque 라이브러리 μ‚¬μš©

    # 처음 μ‹œμž‘ν•  λ•ŒλŠ” μ§„μž…μ°¨μˆ˜κ°€ 0인 λ…Έλ“œλ₯Ό 큐에 μ‚½μž…
    for i in range(1, v + 1):
        if indegree[i] == 0:
            q.append(i)

    # 큐가 빌 λ•ŒκΉŒμ§€ 반볡
    while q:
        # νμ—μ„œ μ›μ†Œ κΊΌλ‚΄κΈ°
        now = q.popleft()
        result.append(now)
        # ν•΄λ‹Ή μ›μ†Œμ™€ μ—°κ²°λœ λ…Έλ“œλ“€μ˜ μ§„μž…μ°¨μˆ˜μ—μ„œ 1 λΉΌκΈ°
        for i in graph[now]:
            indegree[i] -= 1
            # μƒˆλ‘­κ²Œ μ§„μž…μ°¨μˆ˜κ°€ 0이 λ˜λŠ” λ…Έλ“œλ₯Ό 큐에 μ‚½μž…
            if indegree[i] == 0:
                q.append(i)

    # μœ„μƒ 정렬을 μˆ˜ν–‰ν•œ κ²°κ³Ό 좜λ ₯
    for i in result:
        print(i, end=' ')

topology_sort()

 

  • c++
#include <bits/stdc++.h>

using namespace std;

// λ…Έλ“œμ˜ 개수(V)와 κ°„μ„ μ˜ 개수(E)
// λ…Έλ“œμ˜ κ°œμˆ˜λŠ” μ΅œλŒ€ 100,000개라고 κ°€μ •
int v, e;
// λͺ¨λ“  λ…Έλ“œμ— λŒ€ν•œ μ§„μž…μ°¨μˆ˜λŠ” 0으둜 μ΄ˆκΈ°ν™”
int indegree[100001];
// 각 λ…Έλ“œμ— μ—°κ²°λœ κ°„μ„  정보λ₯Ό λ‹΄κΈ° μœ„ν•œ μ—°κ²° 리슀트 μ΄ˆκΈ°ν™”
vector<int> graph[100001];

// μœ„μƒ μ •λ ¬ ν•¨μˆ˜
void topologySort() {
    vector<int> result; // μ•Œκ³ λ¦¬μ¦˜ μˆ˜ν–‰ κ²°κ³Όλ₯Ό 담을 리슀트
    queue<int> q; // 큐 라이브러리 μ‚¬μš©

    // 처음 μ‹œμž‘ν•  λ•ŒλŠ” μ§„μž…μ°¨μˆ˜κ°€ 0인 λ…Έλ“œλ₯Ό 큐에 μ‚½μž…
    for (int i = 1; i <= v; i++) {
        if (indegree[i] == 0) {
            q.push(i);
        }
    }

    // 큐가 빌 λ•ŒκΉŒμ§€ 반볡
    while (!q.empty()) {
        // νμ—μ„œ μ›μ†Œ κΊΌλ‚΄κΈ°
        int now = q.front();
        q.pop();
        result.push_back(now);
        // ν•΄λ‹Ή μ›μ†Œμ™€ μ—°κ²°λœ λ…Έλ“œλ“€μ˜ μ§„μž…μ°¨μˆ˜μ—μ„œ 1 λΉΌκΈ°
        for (int i = 0; i < graph[now].size(); i++) {
            indegree[graph[now][i]] -= 1;
            // μƒˆλ‘­κ²Œ μ§„μž…μ°¨μˆ˜κ°€ 0이 λ˜λŠ” λ…Έλ“œλ₯Ό 큐에 μ‚½μž…
            if (indegree[graph[now][i]] == 0) {
                q.push(graph[now][i]);
            }
        }
    }

    // μœ„μƒ 정렬을 μˆ˜ν–‰ν•œ κ²°κ³Ό 좜λ ₯
    for (int i = 0; i < result.size(); i++) {
        cout << result[i] << ' ';
    }
}

int main(void) {
    cin >> v >> e;

    // λ°©ν–₯ κ·Έλž˜ν”„μ˜ λͺ¨λ“  κ°„μ„  정보λ₯Ό μž…λ ₯ λ°›κΈ°
    for (int i = 0; i < e; i++) {
        int a, b;
        cin >> a >> b;
        graph[a].push_back(b); // 정점 Aμ—μ„œ B둜 이동 κ°€λŠ₯
        // μ§„μž… 차수λ₯Ό 1 증가
        indegree[b] += 1;
    }

    topologySort();
}
  • java
import java.util.*;

public class Main {

    // λ…Έλ“œμ˜ 개수(V)와 κ°„μ„ μ˜ 개수(E)
    // λ…Έλ“œμ˜ κ°œμˆ˜λŠ” μ΅œλŒ€ 100,000개라고 κ°€μ •
    public static int v, e;
    // λͺ¨λ“  λ…Έλ“œμ— λŒ€ν•œ μ§„μž…μ°¨μˆ˜λŠ” 0으둜 μ΄ˆκΈ°ν™”
    public static int[] indegree = new int[100001];
    // 각 λ…Έλ“œμ— μ—°κ²°λœ κ°„μ„  정보λ₯Ό λ‹΄κΈ° μœ„ν•œ μ—°κ²° 리슀트 μ΄ˆκΈ°ν™”
    public static ArrayList<ArrayList<Integer>> graph = new ArrayList<ArrayList<Integer>>();

    // μœ„μƒ μ •λ ¬ ν•¨μˆ˜
    public static void topologySort() {
        ArrayList<Integer> result = new ArrayList<>(); // μ•Œκ³ λ¦¬μ¦˜ μˆ˜ν–‰ κ²°κ³Όλ₯Ό 담을 리슀트
        Queue<Integer> q = new LinkedList<>(); // 큐 라이브러리 μ‚¬μš©

        // 처음 μ‹œμž‘ν•  λ•ŒλŠ” μ§„μž…μ°¨μˆ˜κ°€ 0인 λ…Έλ“œλ₯Ό 큐에 μ‚½μž…
        for (int i = 1; i <= v; i++) {
            if (indegree[i] == 0) {
                q.offer(i);
            }
        }

        // 큐가 빌 λ•ŒκΉŒμ§€ 반볡
        while (!q.isEmpty()) {
            // νμ—μ„œ μ›μ†Œ κΊΌλ‚΄κΈ°
            int now = q.poll();
            result.add(now);
            // ν•΄λ‹Ή μ›μ†Œμ™€ μ—°κ²°λœ λ…Έλ“œλ“€μ˜ μ§„μž…μ°¨μˆ˜μ—μ„œ 1 λΉΌκΈ°
            for (int i = 0; i < graph.get(now).size(); i++) {
                indegree[graph.get(now).get(i)] -= 1;
                // μƒˆλ‘­κ²Œ μ§„μž…μ°¨μˆ˜κ°€ 0이 λ˜λŠ” λ…Έλ“œλ₯Ό 큐에 μ‚½μž…
                if (indegree[graph.get(now).get(i)] == 0) {
                    q.offer(graph.get(now).get(i));
                }
            }
        }

        // μœ„μƒ 정렬을 μˆ˜ν–‰ν•œ κ²°κ³Ό 좜λ ₯
        for (int i = 0; i < result.size(); i++) {
            System.out.print(result.get(i) + " ");
        }
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        v = sc.nextInt();
        e = sc.nextInt();

        // κ·Έλž˜ν”„ μ΄ˆκΈ°ν™”
        for (int i = 0; i <= v; i++) {
            graph.add(new ArrayList<Integer>());
        }

        // λ°©ν–₯ κ·Έλž˜ν”„μ˜ λͺ¨λ“  κ°„μ„  정보λ₯Ό μž…λ ₯ λ°›κΈ°
        for (int i = 0; i < e; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            graph.get(a).add(b); // 정점 Aμ—μ„œ B둜 이동 κ°€λŠ₯
            // μ§„μž… 차수λ₯Ό 1 증가
            indegree[b] += 1;
        }

        topologySort();
    }
}

 

 

 

 

 

=> μ°¨λ‘€λŒ€λ‘œ λͺ¨λ“  λ…Έλ“œλ₯Ό ν™•μΈν•˜λ©° 각 λ…Έλ“œμ—μ„œ λ‚˜κ°€λŠ” 간선을 μ°¨λ‘€λŒ€λ‘œ 제거

=> μ‹œκ°„ λ³΅μž‘λ„λŠ” O(V+E)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
λ°˜μ‘ν˜•
Comments