Kruskal's Algorithm

๊ทธ๋ž˜ํ”„ ์ค‘์—์„œ MST (Minumum Spannig Tree)๋ฅผ ์ฐพ๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ค‘์— ํ•˜๋‚˜์ด๋‹ค.

Union-Find์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•˜๋ฉฐ, ๊ฐ„์„  (edge)์˜ ๊ฐ€์ค‘์น˜(weight)๋ฅผ ์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜์—ฌ ๊ฐ€์ค‘์น˜๊ฐ€ ์‚ฌ์ดํด์ด ์ƒ๊ธฐ์ง€ ์•Š๋Š” ๋‚ฎ์€ ๊ฐ„์„ ์„ ๋จผ์ € ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•.

์‚ฌ์ดํด์˜ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ• ๋•Œ union-find ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์ด์šฉํ•˜์—ฌ ์ฐพ๊ฒŒ ๋œ๋‹ค.

union find ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์„ค๋ช… ๋ณด๊ธฐ

ํŠน์ง•

  • ํƒ์š•์ ์ธ ๋ฐฉ๋ฒ•( Greedy Method )

  • ๊ฐ„์„  ์„ ํƒ ๊ธฐ๋ฐ˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜

  • ๊ฐ„์„  ์„ ํƒ ๋‹จ๊ณ„์—์„œ ์‚ฌ์ดํด์„ ํฌํ•จํ•˜์ง€ ์•Š๊ณ  ์ตœ์†Œ ๋น„์šฉ ๊ฐ„์„ ์„ ์„ ํƒ

  • ๋ถ€๋ถ„ ํŠธ๋ฆฌ์ง‘ํ•ฉ์„ ๋ณ‘ํ•ฉํ•˜๋ฉด์„œ ํ•˜๋‚˜์˜ ํŠธ๋ฆฌ๋กœ ํ™•์žฅ

  • ํฌ์†Œ๊ทธ๋ž˜ํ”„์— ์ ํ•ฉ ( V > E )

  • ์ •๋ ฌ ์†๋„๊ฐ€ ์‹œ๊ฐ„๋ณต์žก๋„์— ์˜ํ–ฅ

Pesudo Code

algorithm Kruskal(G) is
    T := โˆ…
    for each v โˆˆ G.V do
        MAKE-SET(v)
    for each (u, v) in G.E ordered by weight(u, v), increasing do
        if FIND-SET(u) โ‰  FIND-SET(v) then
           T := T โˆช {(u, v)}
           UNION(FIND-SET(u), FIND-SET(v))
    return T

๊ตฌํ˜„

1. ๊ทธ๋ž˜ํ”„์˜ edge(๊ฐ„์„ )์˜ ๊ฐ€์ค‘์น˜(๋น„์šฉ)์„ ์ž‘์€๊ฒƒ ๋ถ€ํ„ฐ ํฐ ์ˆœ์„œ๋Œ€๋กœ(์˜ค๋ฆ„์ฐจ์ˆœ)์œผ๋กœ ์ •๋ ฌ ํ•œ๋‹ค.

2. ๋ชจ๋“  ๊ฐ„์„ ์— ๋Œ€ํ•ด ํ•ด๋‹น ๊ฐ„์„ ์˜ ๋‘ vertex(์ •์ )๊ฐ€ ๊ฐ™์€ ์ง‘ํ•ฉ์— ์†ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌ(Find)ํ•œ๋‹ค.

3-1. ๋‘ vertex(์ •์ )์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ๋“ค์ด ์„œ๋กœ ๋‹ค๋ฅด๋‹ค๋ฉด, ํ•ฉ์ณ(union) ์ค€๋‹ค.

3-2. ๋‘ vertex(์ •์ )์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์ด ๊ฐ™์€ ์ง‘ํ•ฉ์ด๋ผ๋ฉด, ์‚ฌ์ดํด์ด ์ƒ์„ฑ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํŒจ์Šคํ•œ๋‹ค.

4. ์ด ์„ ํƒํ•œ edge(๊ฐ„์„ )์˜ ๋น„์šฉ์„ ๊ณ„์‚ฐํ•ด์ค€๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์ดํด์ด ์ƒ์„ฑ๋˜๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๊ธฐ ์œ„ํ•ด union-find์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์“ฐ์ด๋ฉฐ, kruskal ์•Œ๊ณ ๋ฆฌ์ฆ˜์˜ ์‹œ๊ฐ„๋ณต์žก๋„๋Š” edge๋ฅผ ์ •๋ ฌํ•˜๋Š” ์†๋„์™€ ๋ฐ€์ ‘ํ•œ ์—ฐ๊ด€์ด ์žˆ๋‹ค.

์‹œ๊ฐ„๋ณต์žก๋„

make_set ํ•˜๋Š”๋ฐ O(V), ์ •๋ ฌํ•˜๋Š”๋ฐ ๊ฑธ๋ฆฌ๋Š” ์‹œ๊ฐ„์€ T (๊ฐ„์„  E๋ฅผ ๊ฐ€์ง€๊ณ  ์ •๋ ฌ => O(E), O(1), O(ElgE), O(E^2) ๋“ฑ๋“ฑ ์ด ๋  ์ˆ˜์žˆ๋‹ค.)

Unionํ•˜๊ธฐ ์œ„ํ•ด ์ง‘ํ•ฉ์ด ์†ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๋Š” Find๊ฐ€ O(E)๋ฒˆ ์ผ์–ด๋‚˜๋ฉฐ, Find ์— O(lgV)๋ฒˆ ์ผ์–ด๋‚œ๋‹ค. ๋”ฐ๋ผ์„œ Union์„ ๋๋‚ด๋Š”๋ฐ O(ElgV)๋งŒํผ ๊ฑธ๋ฆฐ๋‹ค.

๋•Œ๋ฌธ์— O(ElgV + T)๋งŒํผ ๊ฑธ๋ฆฌ๊ฒŒ ๋œ๋‹ค.

๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์žˆ์–ด, ์šฐ์„  ๋ณธ์ธ์˜ ํž˜์œผ๋กœ ์ž‘์„ฑํ•ด๋ณด๊ณ  ๋„์ €ํžˆ ์•ˆ๋˜๊ฒ ์„ ๋•Œ ์•„๋ž˜์˜ ์ฝ”๋“œ๋ฅผ ๋ณด์ž.

๊ตฌํ˜„ ์ฝ”๋“œ

๊ตฌํ˜„ ๋ฐฉ๋ฒ•์€ ์‚ฌ๋žŒ๋งˆ๋‹ค ์ •๋ง ๋‹ค์–‘ํ•˜๋‹ˆ ์ฐธ๊ณ ๋งŒ ํ•˜๋„๋ก ํ•˜์ž

์†Œ์Šค์ฝ”๋“œ c++ ( ์ ‘๊ธฐ / ํŽผ์น˜๊ธฐ )

#include <iostream>
#include <algorithm>    //sort
#include <vector>       //vector
#include <cstdlib>      //rand
#include <ctime>        //time

typedef struct edge {
    int src;    //์ถœ๋ฐœ vertex
    int dest;   //๋„์ฐฉ vertex
    int weight; //๊ฐ€์ค‘์น˜(๋น„์šฉ)
} edge;

class Edge {
   private:
    edge e;

   public:
    Edge(int src = 0, int dest = 0, int weight = 0) {
        this->e.src = src;
        this->e.dest = dest;
        this->e.weight = weight;
    }
    int getSrc() { return this->e.src; }
    int getDest() { return this->e.dest; }
    int getWeight() { return this->e.weight; }
    bool operator<(Edge &edge) { return this->e.weight < edge.e.weight; }
};

int Kruskal(std::vector<Edge> &);
int Find(std::vector<int> &, int);
bool Union(std::vector<int> &, std::vector<int> &, int, int);
void randomPush(std::vector<Edge> &);   //graph์— ์‚ฌ์ดํด ์—†๋Š” ์—ฐ๊ฒฐ๊ทธ๋ž˜ํ”„ ๋ฌด์ž‘์œ„ ์ƒ์„ฑ

int V;

int main() {
    std::vector<Edge> g;    //graph g
    int minimum_weight = 0; //minimum cost

    randomPush(g);  //๊ฐ„์„  random ์‚ฝ์ž…

    /*edge info print*/
    std::cout << "edge info : \n";
    std::for_each(g.begin(), g.end(), [](Edge a) {
        std::cout << "src : " << a.getSrc() << " desc : " << a.getDest() << " weight : " << a.getWeight() << std::endl;
    });

    minimum_weight = Kruskal(g);    //kruskal algorithm

    std::cout << "minimum cost : " << minimum_weight << std::endl;  //minimum cost print

    return 0;
}

int Kruskal(std::vector<Edge> &g) {
    int sum = 0;

    /*set, rank ์ดˆ๊ธฐํ™” == > make_set */
    std::vector<int> set(V);
    std::vector<int> rank(V, 0);
    for (int i = 0; i < V; i++) {
        set[i] = i;
    }

    sort(g.begin(), g.end());  //์˜ค๋ฆ„์ฐจ์ˆœ์œผ๋กœ ์ •๋ ฌ

    /*minumum edge ์„ ํƒ*/
    std::cout << "\nselected edge : \n";
    for (int i = 0; i < g.size(); i++) {
        if (Union(set, rank, g[i].getSrc(), g[i].getDest())) {
            std::cout << "edge : " << g[i].getSrc() << " " << g[i].getDest() << " weight : " << g[i].getWeight() << std::endl;
            sum += g[i].getWeight();
        }
    }
    return sum;
}

int Find(std::vector<int> &set, int x) {
    if (set[x] == x)
        return x;
    return set[x] = Find(set, set[x]);
}

bool Union(std::vector<int> &set, std::vector<int> &rank, int x, int y) {
    x = Find(set, x);
    y = Find(set, y);

    if (x == y) return false;

    /*์ง‘ํ•ฉ์— ์•ˆ์†ํ•ด์žˆ๋‹ค๋ฉด  union*/
    if (rank[x] < rank[y])
        set[x] = y;

    else if (rank[x] > rank[y])
        set[y] = x;
    else {
        set[y] = x;
        rank[x]++;
    }
    return true;
}

/*vertex์ˆ˜ ์ž…๋ ฅ๋ฐ›์€ ํ›„ ๊ทธ๋ž˜ํ”„ ๊ฐ„์„  ๊ฐ€์ค‘์น˜ random ์‚ฝ์ž…*/
void randomPush(std::vector<Edge> &g) {
    std::cout << "create number of Vertex : ";
    std::cin >> V;

    srand((unsigned int)time(NULL));

    for (int i = 0; i < V - 1; i++) {
        g.push_back(Edge(i, i + 1, rand() % 100));
        for (int j = i + 1; j < V; j += (rand() % 4)) {
            g.push_back(Edge(i, j, rand() % 100));
        }
    }
    for (int i = V - 1; i > 0; i--) {
        g.push_back(Edge(i, i - 1, rand() % 100));
        for (int j = i - 1; j > 0; j -= (rand() % 4)) {
            g.push_back(Edge(i, j, rand() % 100));
        }
    }
}

Last updated