๊ทธ๋ํ ์ค์์ 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 ));
}
}
}