๊ทธ๋ž˜ํ”„ ์•Œ๊ณ ๋ฆฌ์ฆ˜

9/13/2025

์ตœ๋‹จ๊ฒฝ๋กœ ์•Œ๊ณ ๋ฆฌ์ฆ˜

Unweighted graph (BFS)

๋„ˆ๋น„ ์šฐ์„  ํƒ์ƒ‰ BFS ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•œ๋‹ค.
๊ฐ€์ค‘์น˜๊ฐ€ ์—†๋Š” ๊ทธ๋ž˜ํ”„์—์„œ ์‹œ์ž‘์ ์—์„œ ๋ชฉํ‘œ์ ๊นŒ์ง€์˜ ์ตœ๋‹จ ๊ฒฝ๋กœ๋Š” ๊ฐ€์žฅ ์ ์€ ์ˆ˜์˜ ๊ฐ„์„ ์„ ๊ฐ€์ง€๋Š” ๊ฒฝ๋กœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
BFS์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋ณต์žกํ•˜๊ฒŒ ์–ฝํ˜€์žˆ๋Š” ๊ทธ๋ž˜ํ”„๋ฅผ ์‹œ์ž‘์ ์„ ๋ฃจํŠธ๋กœ ํ•˜๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ์žฌ๊ตฌ์„ฑ์„ ํ•˜๋Š”๊ฒƒ๊ณผ ๋น„์Šทํ•˜๋‹ค(๊ณ  ์ƒ๊ฐํ•œ๋‹ค).
๊ทธ๋ž˜์„œ ๋ชฉ์ ์ง€ ๋…ธ๋“œ๊ฐ€ ์†ํ•œ ๋ ˆ๋ฒจ์„ ๊ตฌํ•˜๋ฉด ๊ทธ๊ฒŒ ๊ณง ์ตœ๋‹จ ๊ฑฐ๋ฆฌ๊ฐ€ ๋˜๊ณ  ํ•ด๋‹น ๊ฒฝ๋กœ ์ƒ์˜ ๊ฐ„์„ ๋“ค์˜ ๋ชจ์Œ์ด ์ตœ๋‹จ๊ฒฝ๋กœ๊ฐ€ ๋œ๋‹ค.

์‚ฌ๊ฑด ๋ณต์žก๋„๋Š” O(V+E).

function bfsShortestPath(graph, start, end) {
    const queue = [[start, [start]]];
    const visited = new Set([start]);
    
    while (queue.length > 0) {
        const [node, path] = queue.shift();
        
        if (node === end) {
            return path;
        }
        
        for (const neighbor of graph[node]) {
            if (!visited.has(neighbor)) {
                visited.add(neighbor);
                queue.push([neighbor, [...path, neighbor]]);
            }
        }
    }
    
    return null;
}

const graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'D'],
    'D': ['B', 'C', 'F'],
    'E': ['B', 'F'],
    'F': ['D', 'E']
};

console.log(bfsShortestPath(graph, 'A', 'F'));

Weighted graph (๋‹ค์ต์ŠคํŠธ๋ผ)

Dijkstra์— ์˜ํ•ด ๊ณ ์•ˆ๋œ ์•Œ๊ณ ๋ฆฌ์ฆ˜.
๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ BFS์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ผ๋ฐ˜ํ™”ํ•œ ๊ฒƒ์ด๋‹ค. (์™œ '์ผ๋ฐ˜ํ™”'๋ผ๊ณ  ํ•˜๋ƒ๋ฉด, unweighted graph๋Š” ๋ชจ๋“  ๊ฐ„์„ ์˜ ๊ฐ€์ค‘์น˜๊ฐ€ 1๋กœ ๋™์ผํ•œ ๋งค์šฐ ํŠน์ˆ˜ํ•œ weighted graph์ด๊ธฐ ๋•Œ๋ฌธ์—.)


class MinHeap {
    constructor() {
        this.heap = [];
    }

    push(val) {
        this.heap.push(val);
        this._heapifyUp(this.heap.length - 1);
    }

    pop() {
        if (this.size() === 0) return null;
        if (this.size() === 1) return this.heap.pop();

        const min = this.heap[0];
        this.heap[0] = this.heap.pop();
        this._heapifyDown(0);
        return min;
    }

    size() {
        return this.heap.length;
    }

    _heapifyUp(index) {
        while (index > 0) {
            const parent = Math.floor((index - 1) / 2);
            if (this.heap[parent][0] <= this.heap[index][0]) break;
            [this.heap[parent], this.heap[index]] = [this.heap[index], 
                                this.heap[parent]];
            index = parent;
        }
    }

    _heapifyDown(index) {
        const n = this.heap.length;
        while (true) {
            let smallest = index;
            const left = 2 * index + 1;
            const right = 2 * index + 2;

            if (left < n && this.heap[left][0] < this.heap[smallest][0]){
                smallest = left;
            }
            
            if (right < n && this.heap[right][0] < this.heap[smallest][0]){
                smallest = right;
            }

            if (smallest === index) break;
            [this.heap[smallest], this.heap[index]] = 
                              [this.heap[index], this.heap[smallest]];
            index = smallest;
        }
    }
}

// Function to construct adjacency 
function constructAdj(edges, V) {
    // adj[u] = list of [v, wt]
    const adj = Array.from({ length: V }, () => []);
    // const adj = Array(V).fill().map(()=>[]); ์™€ ๊ฐ™์€ ์ฝ”๋“œ

    for (const edge of edges) {
        const [u, v, wt] = edge;
        adj[u].push([v, wt]);
        adj[v].push([u, wt]); 
    }

    return adj;
}

// Returns shortest distances from src to all other vertices
function dijkstra(V, edges, src, target) {
    const adj = constructAdj(edges, V);
    const minHeap = new MinHeap();
    const dist = Array(V).fill(Number.MAX_SAFE_INTEGER);
    const parent = Array(V).fill(-1);  // ๋ถ€๋ชจ ๋…ธ๋“œ ์ถ”์ ์šฉ

    minHeap.push([0, src]);
    dist[src] = 0;

    while (minHeap.size() > 0) {
        const [d, u] = minHeap.pop();

        // ๋ชฉํ‘œ ๋…ธ๋“œ์— ๋„๋‹ฌํ•˜๋ฉด ์กฐ๊ธฐ ์ข…๋ฃŒ ๊ฐ€๋Šฅ
        if (u === target) break;

        // ์ด๋ฏธ ์ฒ˜๋ฆฌ๋œ ๋…ธ๋“œ๋ผ๋ฉด ์Šคํ‚ต
        if (d > dist[u]) continue;

        for (const [v, weight] of adj[u]) {
            if (dist[v] > dist[u] + weight) {
                dist[v] = dist[u] + weight;
                parent[v] = u;  // v์˜ ๋ถ€๋ชจ๋ฅผ u๋กœ ์„ค์ •
                minHeap.push([dist[v], v]);
            }
        }
    }

    // ๊ฒฝ๋กœ ๋ณต์›
    const path = [];
    let current = target;
    
    if (dist[target] === Number.MAX_SAFE_INTEGER) {
        return { distance: -1, path: [] };  // ๋„๋‹ฌ ๋ถˆ๊ฐ€๋Šฅ
    }

    while (current !== -1) {
        path.unshift(current);
        current = parent[current];
    }

    return { distance: dist[target], path: path };
}

// Driver code
const V = 5;

// edge list format: [u, v, weight]
const edges = [[0, 1, 4], [0, 2, 8], [1, 4, 6], [2, 3, 2], [3, 4, 10]];

const result = dijkstra(V, edges, 0, 3);

// Print shortest distances in one line
console.log(`Distance: ${result.distance}`);
console.log(`Path: ${result.path.join(' -> ')}`);

Minimum Spanning Tree

Spanning Tree ๋ž€ ์–ด๋–ค ๊ทธ๋ž˜ํ”„์˜ spanning tree๋Š” ์–ด๋–ค ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ์ •์ ์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” sub-graph์ด๋ฉด์„œ ๋˜ํ•œ tree์ด๋‹ค.
ํ•œ ๊ทธ๋ž˜ํ”„์—๋Š” ์—ฌ๋Ÿฌ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.
๋‹น์—ฐํžˆ ์—†์„ ์ˆ˜๋„ ์žˆ๋‹ค. ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์€ ๋…ธ๋“œ๊ฐ€ ์žˆ๋Š” disconnected graph์—๋Š” ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์—†๋‹ค.

๊ทธ๋ฆฌ๊ณ  Minimum Spanning Tree๋ž€ ๊ฒฝ๋กœ๋“ค์˜ ๊ฐ€์ค‘์น˜์˜ ํ•ฉ์ด ๊ฐ€์žฅ ๋‚ฎ์œผ๋ฉด์„œ ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ์ •์ ์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” ํŠธ๋ฆฌ๋‹ค.

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ Kruskal Algorithm

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  1. ๋ชจ๋“  ์—ฃ์ง€๋“ค์„ ๊ฐ€์ค‘์น˜ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ
  2. ์ž‘์€ ์ˆœ์„œ๋Œ€๋กœ ํ™•์ธํ•ด๋ณด๋ฉด์„œ ํ•ด๋‹น ์—ฃ์ง€๊ฐ€ ์‚ฌ์ดํด์„ ๋ฐœ์ƒ์‹œํ‚ค๋Š”์ง€ ํ™•์ธ
  3. ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ถ”๊ฐ€ํ•œ๋‹ค.
function kruskalsMST(V, edges) {
    
    // Sort all edges
    edges.sort((a, b) => a[2] - b[2]);
    
    // Traverse edges in sorted order
    const dsu = new DSU(V);
    let cost = 0;
    let count = 0;
    for (const [x, y, w] of edges) {
        
        // Make sure that there is no cycle
        if (dsu.find(x) !== dsu.find(y)) {
            dsu.unite(x, y);
            cost += w;
            if (++count === V - 1) break;
        }
    }
    return cost;
}

// Disjoint set data structure
class DSU {
    constructor(n) {
        this.parent = Array.from({ length: n }, (_, i) => i);
        this.rank = Array(n).fill(1);
    }

    find(i) {
        if (this.parent[i] !== i) {
            this.parent[i] = this.find(this.parent[i]);
        }
        return this.parent[i];
    }

    unite(x, y) {
        const s1 = this.find(x);
        const s2 = this.find(y);
        if (s1 !== s2) {
            if (this.rank[s1] < this.rank[s2]) this.parent[s1] = s2;
            else if (this.rank[s1] > this.rank[s2]) this.parent[s2] = s1;
            else {
                this.parent[s2] = s1;
                this.rank[s1]++;
            }
        }
    }
}

const edges = [
    [0, 1, 10], [1, 3, 15], [2, 3, 4], [2, 0, 6], [0, 3, 5]
];
console.log(kruskalsMST(4, edges));

๊ฒฐ๊ตญ ํ•ต์‹ฌ์€ ํ•ด๋‹น ์—ฃ์ง€๊ฐ€ ์‚ฌ์ดํด์„ ๋งŒ๋“ค์–ด๋‚ด๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๋Š” ๊ณผ์ •์— ์žˆ๋Š”๋‹ค.
์ˆ˜์—…์—์„œ๋Š” ์ง์ ‘ ์ง‘ํ•ฉ์„ ๋งŒ๋“ค์–ด๊ฐ€๋ฉด์„œ ์˜ˆ์‹œ๋ฅผ ๋ณด์•˜๋Š”๋ฐ (๊ทธ๋ž˜์„œ ์ดํ•ดํ•˜๊ธฐ๊ฐ€ ์‰ฌ์› ๋Š”๋ฐ), ์œ„์—์„œ๋Š” ์ง์ ‘ ์ง‘ํ•ฉ์„ ๋งŒ๋“œ๋Š” ๋ฐฉ์‹ ๋Œ€์‹  parent์™€ rank๋ฐฐ์—ด์„ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.

์–ด๋–ป๊ฒŒ ์œ„์˜ ์ฝ”๋“œ๊ฐ€ ๋™์ผํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋‚ด๋†“๋„๋ก ์ž‘์šฉํ•˜๋Š”์ง€ ์‚ดํŽด๋ณด์ž.

  • parent ๋ฐฐ์—ด์€ ๊ฐ ๋…ธ๋“œ๋“ค์ด ์ž์‹ ์ด ์–ด๋А ๋…ธ๋“œ์˜ ์ง‘ํ•ฉ์— ์†ํ•ด์žˆ๋Š”์ง€ ๋‚˜ํƒ€๋‚ธ๋‹ค. [0,1,2,3]์—์„œ [0,1,2,2] ๊ฐ€ ๋˜๋ฉด 3๋ฒˆ์ด 2๋ฒˆ ๋…ธํŠธ์˜ ์ง‘ํ•ฉ์— ๋“ค์–ด๊ฐ”๋‹ค๋Š” ๋œป.
  • unite()ํ•จ์ˆ˜๋Š” ๋‘ ๋…ธ๋“œ์˜ ์ง‘ํ•ฉ์ค‘์— rank๊ฐ€ ๋‚ฎ์€ ์ชฝ์„ ๋†’์€ ์ชฝ์— ํ•ฉ์นœ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋Š” ์ด์œ ๋Š” (๋‹น์—ฐํ•˜๊ฒŒ๋„) ์ด ๋ฐฉ๋ฒ•์ด ํ›จ์”ฌ ํšจ์œจ์ ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด O(1)์˜ ์†๋„๋กœ ์ง‘ํ•ฉ์„ ํ•ฉ์น˜๋Š” ํšจ๊ณผ๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—. (๋ฐ˜๋ฉด์— ๊ณต๊ฐ„ ๋ณต์žก๋„๋Š” ๋” ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๊ณ  ํ•œ๋‹ค.)

O(ElogE)O(ElogE) ์‹œ๊ฐ„๋ณต์žก๋„

๋ฐฉ๊ธˆ ์•Œ์•„๋ณธ ๋ฐฉ๋ฒ•์„ ํ†ตํ•ด์„œ find()์™€ unite()ํ•จ์ˆ˜๋Š” ๋ชจ๋‘ O(1) ์˜ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฐ๋‹ค๋Š”๊ฒƒ์„ ํ™•์ธํ–ˆ๋‹ค. ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž์ฒด๊ฐ€ ์ •๋ ฌ + union/find ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ •๋ ฌ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ๊ณง ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์‹œ๊ฐ„๋ณต์žก๋„๊ฐ€ ๋œ๋‹ค.

ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ Prim Algorithm

ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ํก์‚ฌํ•˜๋‹ค. ํ•˜๋‚˜์˜ ๋…ธ๋“œ์—์„œ ์‹œ์ž‘ํ•ด์„œ ๊ทธ๋•Œ๋งˆ๋‹ค ๊ฐ€์ค‘์น˜๊ฐ€ ์ ์€ ์—ฃ์ง€์™€ ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ๋ฅผ ๊ณ„์†ํ•ด์„œ ์ถ”๊ฐ€ํ•ด๋‚˜๊ฐ€๋Š” ๊ฒƒ.

๋‹ค๋ฅธ ์ ์€ ๊ฑฐ๋ฆฌ์— ๋Œ€ํ•œ ์ •์˜๊ฐ€ ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๋‹ค๋ฅด๋‹ค๋Š” ์ .

  • ๋‹ค์ต์ŠคํŠธ๋ผ์—์„œ์˜ ๊ฑฐ๋ฆฌ : ์‹œ์ž‘์ ์—์„œ ๋ชฉํ‘œ ๋…ธ๋“œ๊นŒ์ง€์˜ ์ตœ๋‹จ๊ฒฝ๋กœ ์ดํ•ฉ.
  • ํ”„๋ฆผ์—์„œ์˜ ๊ฑฐ๋ฆฌ : ํ˜„์žฌ MST์—์„œ ํ•ด๋‹น ๋…ธ๋“œ๊นŒ์ง€์˜ ์ตœ์†Œ ๊ฐ„์„  ๊ฐ€์ค‘์น˜.

์‚ฌ์ดํด?

์‚ฌ์ดํด์€ ์ด๋ฏธ ์—ฐ๊ฒฐ๋˜์–ด์žˆ๋Š” ๋…ธ๋“œ๋“ค ์‚ฌ์ด์— ์—ฃ์ง€๊ฐ€ ์ถ”๊ฐ€๋˜๋Š”๊ฒƒ์ธ๋ฐ, ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์—์„œ๋Š” ํ•ญ์ƒ MST ๋ฐ–์˜ ๋…ธ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•ด๋‚˜๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์—†๋‹ค.

O(VlogE)O(VlogE) ์‹œ๊ฐ„๋ณต์žก๋„

ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ์ž‘๋™ ๋ฐฉ์‹์ด ๋˜‘๊ฐ™๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ฐ„ ๋ณต์žก๋„๋„ ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ฐ™์„ ์ˆ˜ ๋ฐ–์— ์—†๋‹ค.