Skip to content

Conversation

@dohyeondol1
Copy link
Contributor

๐Ÿ”— ๋ฌธ์ œ ๋งํฌ

์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ

โœ”๏ธ ์†Œ์š”๋œ ์‹œ๊ฐ„

40m

โœจ ์ˆ˜๋„ ์ฝ”๋“œ

์ˆ˜๋„์ฝ”๋“œ
ํ•จ์ˆ˜ prim(์ •์  ์ˆ˜ V, ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ adj):
    visited ๋ฐฐ์—ด์„ V ํฌ๊ธฐ๋งŒํผ false๋กœ ์ดˆ๊ธฐํ™”
    ์ตœ์†Œ ํž™ pq๋ฅผ ์„ ์–ธ (๊ฐ€์ค‘์น˜ ๊ธฐ์ค€ ์ •๋ ฌ)

    totalWeight๋ฅผ 0์œผ๋กœ ์ดˆ๊ธฐํ™”
    pq์— (0, 0) ์ถ”๊ฐ€  // ์‹œ์ž‘ ์ •์ ์€ 0๋ฒˆ, ๊ฐ€์ค‘์น˜ 0

    while pq๊ฐ€ ๋น„์–ด์žˆ์ง€ ์•Š์œผ๋ฉด:
        (weight, u)๋ฅผ pq์—์„œ ๊บผ๋ƒ„

        ๋งŒ์•ฝ u๊ฐ€ ์ด๋ฏธ ๋ฐฉ๋ฌธ๋œ ์ •์ ์ด๋ฉด:
            ๊ณ„์† ์ง„ํ–‰

        u๋ฅผ ๋ฐฉ๋ฌธ ์ฒ˜๋ฆฌ
        totalWeight์— weight๋ฅผ ๋”ํ•จ

        for adj[u]์˜ ๋ชจ๋“  (w, v)์— ๋Œ€ํ•ด:
            ๋งŒ์•ฝ v๊ฐ€ ๋ฐฉ๋ฌธ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด:
                pq์— (w, v)๋ฅผ ์ถ”๊ฐ€

    totalWeight ๋ฐ˜ํ™˜


๋ฉ”์ธ ํ•จ์ˆ˜:
    ์ž…๋ ฅ ์ตœ์ ํ™”๋ฅผ ์„ค์ •

    ์ •์  ์ˆ˜ V, ๊ฐ„์„  ์ˆ˜ E ์ž…๋ ฅ
    V ํฌ๊ธฐ์˜ ์ธ์ ‘ ๋ฆฌ์ŠคํŠธ adj ์ดˆ๊ธฐํ™”

    E๊ฐœ์˜ ๊ฐ„์„ ์„ ์ž…๋ ฅ์œผ๋กœ ๋ฐ›์Œ:
        ๊ฐ ๊ฐ„์„ ์˜ A, B, C๋ฅผ ์ž…๋ ฅ๋ฐ›๊ณ 
        A์™€ B๋ฅผ 0๋ถ€ํ„ฐ ์‹œ์ž‘ํ•˜๋„๋ก ์กฐ์ •
        adj[A]์— (C, B) ์ถ”๊ฐ€
        adj[B]์— (C, A) ์ถ”๊ฐ€  // ๋ฌด๋ฐฉํ–ฅ ๊ทธ๋ž˜ํ”„

    prim(V, adj)๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ MST ๊ฐ€์ค‘์น˜๋ฅผ ๊ตฌํ•จ
    ๊ฒฐ๊ณผ ์ถœ๋ ฅ

์ด ๋ฌธ์ œ๋Š” ๋ฌธ์ œ ์ด๋ฆ„๋Œ€๋กœ MST(Minimum Spanning Tree, ์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ)๋ฅผ ๊ตฌํ•˜๋Š” ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค.

์ตœ์†Œ ์ŠคํŒจ๋‹ ํŠธ๋ฆฌ๋Š”, ์ฃผ์–ด์ง„ ๊ทธ๋ž˜ํ”„์˜ ๋ชจ๋“  ์ •์ ๋“ค์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋ถ€๋ถ„ ๊ทธ๋ž˜ํ”„ ์ค‘์—์„œ ๊ทธ ๊ฐ€์ค‘์น˜์˜ ํ•ฉ์ด ์ตœ์†Œ์ธ ํŠธ๋ฆฌ๋ฅผ ๋งํ•œ๋‹ค.

MST๋ฅผ ๊ตฌํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์—๋Š” ๋Œ€ํ‘œ์ ์œผ๋กœ ์ž˜ ์•Œ๋ ค์ง„ ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค.

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

ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ œ๊ฐ€ ๋‹ค์ต์ŠคํŠธ๋ผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ํ•˜๊ณ  ๊ฑฐ์˜ ๋˜‘๊ฐ™๋‹ค๊ณ  ๋А๋‚€ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

  1. ์ž„์˜์˜ ์ •์ ์„ ์„ ํƒํ•˜์—ฌ ํ•˜๋‚˜์˜ ์ •์ ์„ ๊ฐ–๋Š” ์ตœ์ดˆ์˜ ํŠธ๋ฆฌ๋ฅผ ๊ตฌ์„ฑํ•œ๋‹ค.
  2. ํŠธ๋ฆฌ์— ํฌํ•จ๋œ ์ •์ ๊ณผ ํŠธ๋ฆฌ์— ํฌํ•จ๋˜์ง€ ์•Š์€ ์ •์  ๊ฐ„์˜ ๊ฐ„์„  ์ค‘ ๊ฐ€์žฅ ์ž‘์€ ๊ฐ€์ค‘์น˜๋ฅผ ๊ฐ€์ง€๋Š” ๊ฐ„์„ ์„ ์„ ํƒํ•˜์—ฌ ํŠธ๋ฆฌ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
  3. ๋ชจ๋“  ์ •์ ์ด ํŠธ๋ฆฌ์— ํฌํ•จ๋  ๋•Œ๊นŒ์ง€ 2๋ฅผ ๋ฐ˜๋ณตํ•œ๋‹ค.

Prim-animation

์ด ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๋‹ค์ต์ŠคํŠธ๋ผ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„
#include <vector>
#include <queue>
#include <utility>
#include <limits>

using namespace std;

using Graph = vector<vector<pair<int, int>>>; // (neighbor, weight)
using pii = pair<int, int>; // (weight, vertex)

vector<int> prim(const Graph& graph, int start = 0) {
    int n = graph.size();
    vector<bool> visited(n, false);
    vector<int> parent(n, -1); // MST๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ํŠธ๋ฆฌ ์ •๋ณด
    vector<int> minWeight(n, numeric_limits<int>::max());

    priority_queue<pii, vector<pii>, greater<>> pq;
    minWeight[start] = 0;
    pq.emplace(0, start);

    while (!pq.empty()) {
        auto [weight, u] = pq.top();
        pq.pop();

        if (visited[u]) continue;
        visited[u] = true;

        for (auto [v, w] : graph[u]) {
            if (!visited[v] && w < minWeight[v]) {
                minWeight[v] = w;
                parent[v] = u;
                pq.emplace(w, v);
            }
        }
    }

    return parent; // MST์˜ ๊ฐ ๋…ธ๋“œ์˜ ๋ถ€๋ชจ๋ฅผ ๋‚˜ํƒ€๋ƒ„
}

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

์–ด์ฉŒ๋ฉด ํ”„๋ฆผ๋ณด๋‹ค ๋” ์‰ฌ์šด ์•Œ๊ณ ๋ฆฌ์ฆ˜์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ˆœ์„œ๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

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

Kruskal-animation

์ด๋ฅผ ์„œ๋กœ์†Œ ์ง‘ํ•ฉ, Union Find ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๊ตฌํ˜„
#include <vector>
#include <tuple>
#include <algorithm>

using namespace std;

using Edge = tuple<int, int, int>; // (weight, u, v)

struct DisjointSet {
    vector<int> parent, rank;

    DisjointSet(int n) : parent(n), rank(n, 1) {
        for (int i = 0; i < n; ++i) parent[i] = i;
    }

    int find(int u) {
        return parent[u] == u ? u : parent[u] = find(parent[u]);
    }

    bool unite(int u, int v) {
        u = find(u);
        v = find(v);
        if (u == v) return false;

        if (rank[u] < rank[v]) swap(u, v);
        parent[v] = u;
        if (rank[u] == rank[v]) rank[u]++;
        return true;
    }
};

vector<Edge> kruskal(int n, vector<Edge>& edges) {
    sort(edges.begin(), edges.end()); // weight ๊ธฐ์ค€ ์ •๋ ฌ
    DisjointSet ds(n);
    vector<Edge> mst;

    for (const auto& [w, u, v] : edges) {
        if (ds.unite(u, v)) {
            mst.emplace_back(w, u, v);
        }
    }

    return mst; // MST์— ํฌํ•จ๋œ ๊ฐ„์„  ๋ฆฌ์ŠคํŠธ ๋ฐ˜ํ™˜
}

์ €๋Š” ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์‚ฌ์šฉํ•ด์„œ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์˜€์Šต๋‹ˆ๋‹ค.
์•ˆํ’€๋˜ ๊ทธ๋ž˜ํ”„ ๋ฌธ์ œ๋ฅผ ์ข€ ํ’€์–ด๋ณด๋ ค๋‹ค ๋ณด๋‹ˆ MST ๋ฌธ์ œ๋ฅผ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค..

์ œ ์ฝ”๋“œ์—์„œ ๋” ๊น”๋”ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒ ๋‹ค ์‹ถ์€ ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ๋งˆ๊ตฌ๋งˆ๊ตฌ ์•Œ๋ ค์ฃผ์„ธ์šฉ~~ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

๐Ÿ“š ์ƒˆ๋กญ๊ฒŒ ์•Œ๊ฒŒ๋œ ๋‚ด์šฉ

@froglike6
Copy link
Collaborator

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

import sys
input = sys.stdin.readline

def find(x):
    while parent[x] != x:
        parent[x] = parent[parent[x]]
        x = parent[x]
    return x

def union(a, b):
    ra = find(a)
    rb = find(b)
    if ra != rb:
        parent[rb] = ra

v, e = map(int, input().split())
parent = [i for i in range(v+1)]

edge = []
for _ in range(e):
    a, b, c = map(int, input().split())
    edge.append((c, a, b))
edge.sort()

ans = 0
for w, u, v in edge:
    if find(u) != find(v):
        union(u, v)
        ans += w
print(ans)

@dohyeondol1
Copy link
Contributor Author

์นผ๋ฆฌ๋ทฐ ใ„ทใ„ท

@Fnhid
Copy link
Collaborator

Fnhid commented Jul 11, 2025

์ž๋ฃŒ๊ตฌ์กฐ ์‹œ๊ฐ„์— ๋ณด์•˜๋˜ MST๋ฅผ ์—ฌ๊ธฐ์„œ ๋ณด๋‹ˆ ๋ฐ˜๊ฐ‘๋„ค์š”.

ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ๊ฐ„์„ ์„ ์ •๋ ฌํ•œ ๋‹ค์Œ ์ตœ์†Œ ๋น„์šฉ ๊ฐ„์„ ๋ถ€ํ„ฐ ์‚ฌ์ดํด์ด ๋ฐœ์ƒํ•˜๋Š”์ง€ ์ฒดํฌํ•˜๋Š” ๋กœ์ง์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ„์„ ์„ ์ •๋ ฌํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์„ ๊ฐ€์žฅ ๋งŽ์ด ์†Œ๋ชจํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ( $$O(E log E)$$ )

๋ฐ˜๋ฉด ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์€ ์ธ์ ‘ ๋ฐฐ์—ด๋กœ Greedyํ•˜๊ฒŒ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ๋„ํ˜„๋‹˜์ด ๋ง์”€ํ•˜์‹  ์šฐ์„ ์ˆœ์œ„ ํ๋กœ ์ ‘๊ทผํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”๋ฐ,

์ธ์ ‘ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋ฉด $$O(V^2)$$์˜, ์šฐ์„ ์ˆœ์œ„ ํ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด $$O(ElogV)$$์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๋Š” ๊ฒƒ์œผ๋กœ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ ๊ฐ„์„ ์˜ ์ˆ˜๊ฐ€ ์ ์€ ๊ทธ๋ž˜ํ”„์ผ ๊ฒฝ์šฐ ํฌ๋ฃจ์Šค์นผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋” ํšจ์œจ์ ์ด๊ณ ,
๊ฐ„์„ ์˜ ์ˆ˜๊ฐ€ ๋งŽ์œผ๋ฉด ํ”„๋ฆผ ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ๋” ํšจ์œจ์ ์ธ ๊ฒƒ์œผ๋กœ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

PS์—์„œ๋Š” ์–ด์ฐจํ”ผ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค๊ฐ€ ๋‹ค์–‘ํ•˜๊ฒŒ ๋‚˜์™€์„œ ๋ณ„๋กœ ์ค‘์š”ํ•˜์ง„ ์•Š์€๋ฐ
๊ทธ๋ƒฅ ์•Œ์•„๋‘๋ฉด ๋‚˜์ค‘์— ์“ธ ๊ณณ์ด ์žˆ์ง€ ์•Š์„๊นŒ์š” ๐Ÿซ 

@Fnhid
Copy link
Collaborator

Fnhid commented Jul 11, 2025

๊ทธ๋‚˜์ €๋‚˜ c++ stl์— priority_queue๋„ ์žˆ๊ตฐ์š”.. ์—†๋Š” ๊ฒƒ์ด ์—†๋„ค์š” ใ„ทใ„ท

@dohyeondol1
Copy link
Contributor Author

๊ทธ๋‚˜์ €๋‚˜ c++ stl์— priority_queue๋„ ์žˆ๊ตฐ์š”.. ์—†๋Š” ๊ฒƒ์ด ์—†๋„ค์š” ใ„ทใ„ท

C++์€ ์ž˜ ๋งŒ๋“ค์–ด์ง„ STL์ด ๋งŽ์€ ๊ฒƒ ๊ฐ™์•„์š” ใ…Žใ…Ž

Copy link
Collaborator

@hadongun hadongun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ž๋ฃŒ๊ตฌ์กฐ ๋•Œ ๋ฐฐ์› ๋˜ ๊ฑฐ๋ผ ๊ทธ๋Ÿฐ์ง€ ๊ธฐ์–ต์ด ์ƒ์ƒํ•˜์ง€ ์•Š๋„ค์š” ใ…Žใ…Ž
๊ทธ๋ž˜๋„ ๊ธฐ์–ต์ด ๋‚จ์•„ ์žˆ์–ด ์กฐ๊ธˆ ๊ณต๋ถ€ ํ•œ ํ›„ ํ’€ ์ˆ˜ ์žˆ์—ˆ์–ด์šฉ

ํŒŒ์ด์ฌ์— ์žฌ๊ท€ ํšŸ์ˆ˜ ์ œํ•œ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ๋„ ์ฒ˜์Œ ์•Œ์•˜๋„ค์š”..!
๊ฐ€๋Šฅํ•œ ์žฌ๊ท€ ์ œํ•œ์„ ๋Š˜๋ ค์„œ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํƒ€ ์ŠคํŠธ๋Ÿญ์ณ

import sys
input = sys.stdin.readline
sys.setrecursionlimit(10**7)


V, E = map(int, input().split())

edges = []
for _ in range(E):
    u, v, w = map(int, input().split())
    edges.append((w, u, v))

edges.sort()

parent = [i for i in range(V+1)]

def find(x):
    if parent[x] != x:
        parent[x] = find(parent[x])
    return parent[x]

def union(a, b):
    a = find(a)
    b = find(b)
    if a != b:
        parent[b] = a
        return True
    return False

result = 0
count = 0
for w, u, v in edges:
    if union(u, v):
        result += w
        count += 1
        if count == V-1:
            break

print(result)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants