๊ทธ๋ํ ์ค์์ MST (Minumum Spannig Tree)
๋ฅผ ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ์ค์ ํ๋์ด๋ค.
Union-Find
์๊ณ ๋ฆฌ์ฆ์ ์ด์ฉํ๋ฉฐ, ๊ฐ์ (edge)์ ๊ฐ์ค์น(weight)๋ฅผ ์ค๋ฆ์ฐจ์์ผ๋ก ์ ๋ ฌ
ํ์ฌ ๊ฐ์ค์น๊ฐ ์ฌ์ดํด์ด ์๊ธฐ์ง ์๋
๋ฎ์ ๊ฐ์ ์ ๋จผ์ ์ ํํ๋ ๋ฐฉ๋ฒ.
์ฌ์ดํด์ ์ฌ๋ถ๋ฅผ ํ์ธํ ๋ union-find
์๊ณ ๋ฆฌ์ฆ์ ์ด์ฉํ์ฌ ์ฐพ๊ฒ ๋๋ค.
union find ์๊ณ ๋ฆฌ์ฆ ์ค๋ช
๋ณด๊ธฐ
ํน์ง
ํ์์ ์ธ ๋ฐฉ๋ฒ( Greedy Method )
๊ฐ์ ์ ํ ๊ธฐ๋ฐ ์๊ณ ๋ฆฌ์ฆ
๊ฐ์ ์ ํ ๋จ๊ณ์์ ์ฌ์ดํด์ ํฌํจํ์ง ์๊ณ ์ต์ ๋น์ฉ ๊ฐ์ ์ ์ ํ
๋ถ๋ถ ํธ๋ฆฌ์งํฉ์ ๋ณํฉํ๋ฉด์ ํ๋์ ํธ๋ฆฌ๋ก ํ์ฅ
ํฌ์๊ทธ๋ํ์ ์ ํฉ ( V > E )
์ ๋ ฌ ์๋๊ฐ ์๊ฐ๋ณต์ก๋์ ์ํฅ
Pesudo Code
Copy 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
๊ตฌํ
Copy 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++ ( ์ ๊ธฐ / ํผ์น๊ธฐ )
Copy #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));
}
}
}