๊ทธ๋ํ ์ค์์ ์ต๋จ ๊ฒฝ๋ก
๋ฅผ ์ฐพ๋ ์๊ณ ๋ฆฌ์ฆ์ค์ ํ๋๋ก ํ๋์ ์ ์ ์์ ๋ค๋ฅธ ๋ชจ๋ ์ ์ ๊น์ง์ ์ต๋จ๊ฒฝ๋ก๋ฅผ ๊ตฌํ๋ ์๊ณ ๋ฆฌ์ฆ (single-source shortest path algorithmm)
์ฐ์ ์์ ํ
์ ๋ฐฉ๋ฒ์ ์ด์ฉํ๋ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
vertex๋ฅผ ํ๊ฐ์ฉ ์ ํํ๋ฉฐ ์ต๋จ ๊ฒฝ๋ก๋ฅผ ์ฐพ๋ ๋ฐฉ๋ฒ.
relax
์ ๊ฐ๋
์ ์ด์ฉํ๋ฉฐ relax๋ ํ์ฌ ๊ณ์ฐ๋ v๋
ธ๋๊น์ง์ ๊ฑฐ๋ฆฌ๋ณด๋ค ํ์ฌ ๋
ธ๋ u๊น์ง์ ๊ฒฝ๋ก์ u์์ v์ ๊ฐ์ค์น ( e(u,v)
) ๊ฐ ๋ ์๋ค๋ฉด ๊ฐ์ ๊ฐฑ์ ํด์ฃผ๋ ๊ฒ.
relax
๋ prim ์๊ณ ๋ฆฌ์ฆ์ decrease-key
์ ์ ์ฌํ๋ฉฐ dp๋ฅผ ์ถ๊ฐํ ๊ฐ๋
ํน์ง
ํ์์ ์ธ ๋ฐฉ๋ฒ( Greedy Method )
์์ ๊ฐ์ค์น ํ์ฉ x
์์ ์ ์ ๋ถํฐ ์ถ๋ฐํ์ฌ ์ต์ ๋น์ฉ์ ๊ฐ์ ์ ๊ฐ๋ ์ ์ ์ ์ ํํ์ฌ ์ ์ฅ ํธ๋ฆฌ ์งํฉ์ ๋จ๊ณ์ ์ผ๋ก ํ์ฅ
๋ฐ์ง ๊ทธ๋ํ์ ์ ํฉ
์๋ฃ๊ตฌ์กฐ์ค ํ๋์ธ ์ฐ์ ์์ ํ
๋ฅผ ์ด์ฉํ๋ฉฐ, ์ฐ์ ์์ ํ๋ฅผ ์ด๋ป๊ฒ ๊ตฌํํ๋๊ฐ๊ฐ ์๊ฐ๋ณต์ก๋์ ์ํฅ
Pesudo Code
Copy Dijkstra(G, w , s){
INITIALIZE-SINGLE-SOURCE(G, s)
S <- โ
Q <- V[G]
while Q != โ
do u <- EXTRACT-MIN(โ
)
s <- S โช {u}
for each vertex v โ Adj[u]
do RELAX(u, v, w)
}
Copy RELAX(u,v,w)
if v.d > u.d + w(u,v)
v.d = u.d + w(u,v)
v.ฯ = u
๊ตฌํ ๋ฐฉ๋ฒ
Prim's ์๊ณ ๋ฆฌ์ฆ
์์ decrease key
๋ถ๋ถ์ dp
๋ฅผ ์ด์ฉํ๋ค๋ ๊ฒ ๋นผ๊ณ ๋ค๋ฅธ ๊ฒ์ด ์๋ค.
vertex๋ค์ key๊ฐ์ Infinity๋ก ์ด๊ธฐํํ๋ค.
start vertex์ key๊ฐ์ 0์ผ๋ก ์ด๊ธฐํํ๋ค. (์ด๋ค vertex๋ฅผ ์ ํํ๋๋ผ๊ณ MST๊ฐ ๋์จ๋ค.)
ํ์ฌ vertex์ ์ธ์ ํ vertex๋ค ์ค ์ ํํ์ง ์์๊ณ , ๊ฐ์ฅ vertex์ key๊ฐ์ด ์์ vertex์ ์ฐพ๋๋ค. (exract-min = ์ต์๊ฐ ์ถ์ถ
)
ํ์ฌ vertex๋ฅผ ์ ํํ๋ค.
์ธ์ ํ vertex์ค vertex์ key๊ฐ๋ณด๋ค ๊ฐ์ ์ ๊ฐ์ค์น์ ํ์ฌ๊น์ง์ ๊ฑฐ๋ฆฌ์ ํฉ์ด ๋ ์๋ค๋ฉด key๊ฐ์ ๊ฐ์ค์น์ ํ์ฌ๊น์ง์ ๊ฑฐ๋ฆฌ์ ํฉ์ผ๋ก ๊ฐฑ์ ํ๋ค. (RELAX
)
์ธ์ ํ vertex์ค ์ ํํ์ง ์์๊ณ , ๊ฐ์ฅ vertex์ key๊ฐ์ด ์์ vertex๋ฅผ ๊ธฐ์ค์ผ๋ก 3๋ฒ
๋ถํฐ ๋ค์ ๋ฐ๋ณตํ๋ค.
๋ชจ๋ vertex๊ฐ ์ ํ๋์๋ค๋ฉด ๋๋๋ค.
์ธ์ ํ๋ ฌ
์์ ์ค๋ช
ํ 3๋ฒ ๋ฐฉ๋ฒ
์ extract-min์ ์๋์ ๊ฐ์ด ๋ฐฐ์ด๋ก ๊ตฌํํ๋ฉฐ, ๋งค๋ฒ Vํ ๋ฐ๋ณตํ๋ค.
Copy int v = -1; //์ธ์ vertex์ค ๊ฐ์ฅ ์์ ๊ฐ์ค์น๋ฅผ ๊ฐ๋ vertex
int min_key = INFINITY; //์ธ์ vertex์ค ๊ฐ์ฅ ์์ ๊ฐ์ค์น
/* ์ธ์ vertex์ค ๊ฐ์ฅ ์์ ๊ฐ์ค์น๋ฅผ ๊ฐ๋ vertex ์ฐพ๊ธฐ*/
for (int j = 0; j < V; j++) {
if (!selected[j] && (min_key > vertex_key[j])) {
v = j;
min_key = vertex_key[j];
}
}
์๋๋ 5๋ฒ ๋ฐฉ๋ฒ
์ผ๋ก ์ธ์ ํ vertex์ค vertex์ key๊ฐ๋ณด๋ค ๊ฐ์ ์ ๊ฐ์ค์น์ ํ์ฌ๊น์ง์ ๊ฑฐ๋ฆฌ์ ํฉ์ด ๋ ์๋ค๋ฉด key๊ฐ์ ๊ฐ์ค์น์ ํ์ฌ๊น์ง์ ๊ฑฐ๋ฆฌ์ ํฉ์ผ๋ก ๊ฐฑ์ ํ๋ค.
์ ๋ณด๋ฉด ์๊ฒ ์ง๋ง Prim's ์๊ณ ๋ฆฌ์ฆ
๊ณผ ๋น๊ตํด์ vertex_key[selct_idx]
์ถ๊ฐ ๋์๋ค.
Copy for (int j = 0; j < V; j++) {
if (!selected[j] && vertex_key[j] > adjMatrix[select_idx][j] + vertex_key[select_idx]) {
vertex_key[j] = adjMatrix[select_idx][j] + vertex_key[select_idx];
}
}
์ธ์ ๋ฆฌ์คํธ
์ธ์ ๋ฆฌ์คํธ๋ ์ธ์ ํ vertex์ ๊ฐ์ค์น๋ฅผ priority queue๋ฅผ ํตํด ์ ์ฅํ๋ค.
๋๋ฌธ์, 3๋ฒ ๋ฐฉ๋ฒ์
exract-min์ ๋งจ์์์ pop์ ์์ผ ์ฐพ์์ฃผ๋ฉด ๋๋ค.
Copy int select_key = q.begin()->second;
int min_of_key = q.begin()->first;
q.erase(q.begin());
5๋ฒ ๋ฐฉ๋ฒ
์ผ๋ก ์ธ์ ํ vertex์ค vertex์ key๊ฐ๋ณด๋ค ๊ฐ์ ์ ๊ฐ์ค์น์ ํ์ฌ ์ ์ ๊น์ง์ ๊ฑฐ๋ฆฌ์ ํฉ์ด ๋ ์๋ค๋ฉด key๊ฐ์ ๊ฐ์ค์น์ ํ์ฌ ์ ์ ๊น์ง์ ๊ฑฐ๋ฆฌ์ ํฉ์ผ๋ก ๊ฐฑ์ ํ๋ ๋ฐฉ๋ฒ์ ์๋์ ๊ฐ์ด ์ธ์ ํ ๊ฐ์ ์ ๊ฐ์๋งํผ ์ํํ๋ค.
Copy /*selectํ vertex์ ์ธ์ ํ ๊ฐ์ ์ธ e*/
for (auto e : adjList[select_key]) {
if (!selected[e.second] && vertex_key[e.second] > e.first + vertex_key[select_key]) {
q.erase({vertex_key[e.second], e.second}); //๊ฐ์ ๋
ธ๋๋ก ํฅํ๋ ๊ฐ์ ์ค weight๊ฐ ๋ ์์ ๊ฐ์ ์ด ์๋ค๋ฉด ๊ทธ ์ ๊ฐ์ ์ ์ญ์
q.insert({e.first, e.second}); //ํ์ ์ฝ์
vertex_key[e.second] = e.first + vertex_key[select_key];
}
ใ
}
์๊ฐ ๋ณต์ก๋
Prim's ์๊ณ ๋ฆฌ์ฆ
๊ณผ ๋์ผํ๋ค.
์๊ฐ๋ณต์ก๋๋ ์ด๊ธฐํํ๋๋ฐ O(|V|), MST๊ณ์ฐํ๋๋ฐ O(|V|) * T(extract-min) (๊ฐ์ฅ ์ ์ ๊ฐ ์ถ์ถํ๋๋ฐ ๊ฑธ๋ฆฐ์๊ฐ) + O(|E|) * T(RELAX) ( key๊ฐ ๋ณ๊ฒฝํ๋๋ฐ ๊ฑธ๋ฆฌ๋ ์๊ฐ )์ ๊ฐ๋ค.
๋ฐ๋ผ์, priority-queue๋ฅผ ์ด๋ป๊ฒ ๊ตฌํํ๋์ง์ ๋ฐ๋ผ ์๊ฐ๋ณต์ก๋๊ฐ ๋ฌ๋ผ์ง๋ค.
์ผ๋ฐ ๋ฐฐ์ด๋ก ๊ตฌํํ์ ๊ฒฝ์ฐ T(extract)๊ฐ O(|V|), T(RELAX)๋ O(1)๋งํผ ๊ฑธ๋ ค ์ด O(|V^2|)์ด ๊ฑธ๋ฆฐ๋ค.
binary heap(์ด์ง ํ)์ผ๋ก ๊ตฌํํ๋ฉด T(extract)๊ฐ O(lgV), T(RELAX)๋ O(lgV)๋งํผ ๊ฑธ๋ ค ์ด O(VlgV) + O(ElgV) ์ด๊ธฐ ๋๋ฌธ์ O((E+V)lgV)๋งํผ ๊ฑธ๋ฆฐ๋ค.
๋ฌด๋ฐฉํฅ ๊ทธ๋ํ์ผ๋ E์ ์ต์๊ฐ์ V-1๋ก ๊ฑฐ์ ๋๋ถ๋ถ์ด |E| > |V| ์ด๋ฏ๋ก O(|E|lg|V|)๋ผ๊ณ ํ ์ ์๋ค.
priority queue๋ฅผ ์ด์ง ํ์ด ์๋ fibonacci heap์ผ๋ก ๊ตฌํํ๋ฉด RELAX์ ์๊ฐ์ ์ข๋ ์ค์ผ ์ ์๋ค.
RELAX์๊ฐ์ด O(1)๋งํผ ๊ฑธ๋ฆฌ๊ธฐ ๋๋ฌธ์ O(E+VlgV)๋ผ๊ณ ํ ์ ์๋ค.
O(E) or O(VlgV) ์ธ ์ด์ ๋ ์ต์
์ ๊ฒฝ์ฐ์ E๋ O(V^2)์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๊ตฌํ ์ฝ๋
์๋ ์ฝ๋๋ ์ฌ์ดํด์ด์๋ ๋ฌด๋ฐฉํฅ์ ๊ทธ๋ํ์ด๊ณ , ๊ฐ์ค์น๋ฅผ ๋ฌด์์๋ก ์์ฑํ ๊ทธ๋ํ์ด๋ค.
์์ค์ฝ๋ c++ ( ์ ๊ธฐ / ํผ์น๊ธฐ )
Copy #include <time.h> //์๊ฐ ์ธก์
#include <algorithm> //for_each
#include <cstdlib> //rand
#include <ctime> //time
#include <iostream>
#include <set>
#include <vector>
#define INFINITY 2147483647
#define II std::pair<int, int> // first = weight, second = dest
typedef struct edge {
int src; //์ถ๋ฐ vertex
int dest; //๋์ฐฉ vertex
int weight; //๊ฐ์ค์น(๋น์ฉ)
} edge;
class Graph {
private:
edge e;
public:
Graph(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; }
};
void CalcTime();
void randomPush(std::vector<Graph> &); // graph์ ์ฌ์ดํด ์๋ ์ฐ๊ฒฐ๊ทธ๋ํ cost๊ฐ ๋ฌด์์ ์์ฑ
void print_edge_info(std::vector<Graph>); // graph ๊ฐ์ ๋ค ๋ณด๊ธฐ
void make_adj_list(std::vector<Graph>, std::vector<std::vector<II>> &); //์ฃผ์ด์ง ๊ทธ๋ํ๋ฅผ ์ธ์ ๋ฆฌ์คํธ๋ก ํํ
void make_adj_matrix(std::vector<Graph>, std::vector<std::vector<int>> &); //์ฃผ์ด์ง ๊ทธ๋ํ๋ฅผ ์ธ์ ํ๋ ค๋ก ํํ
int dijkstra_heap(std::vector<Graph> &, std::vector<std::vector<II>>, int);
int dijkstra_array(std::vector<Graph> &, std::vector<std::vector<int>>, int);
int V; // vertex ๊ฐ์
clock_t start, finish, used_time = 0; //์คํ ์๊ฐ ์ธก์ ์ ์ํ ๋ณ์
int main() {
std::vector<Graph> g; // graph g
int minimum_weight = 0; // minimum cost
std::vector<std::vector<int>> adjMatrix;
std::vector<std::vector<II>> adjList;
randomPush(g); //๊ฐ์ random ์ฝ์
// 10print_edge_info(g); // edge info print
make_adj_matrix(g, adjMatrix); //์ฃผ์ด์ง ๊ทธ๋ํ๋ฅผ ์ธ์ ํ๋ ฌ๋ก ๋ง๋ค๊ธฐ
make_adj_list(g, adjList); //์ฃผ์ด์ง ๊ทธ๋ํ๋ฅผ ์ธ์ ๋ฆฌ์คํธ๋ก ๋ง๋ค๊ธฐ
start = clock();
// minimum_weight = dijkstra_heap(g, adjList, 0); //binary heap์ ์ด์ฉํ ๊ตฌํ
minimum_weight = dijkstra_array(g, adjMatrix, 0); // array ์ด์ฉํ ๊ตฌํ
finish = clock();
std::cout << "\nall route dis : " << minimum_weight << std::endl;
CalcTime();
return 0;
}
int dijkstra_heap(std::vector<Graph> &g, std::vector<std::vector<II>> adjList, int start) {
int sum = 0;
std::set<II> q; //์ด์งํ์ผ๋ก queue ๋ง๋ค๊ธฐ ( set์ red-black tree๋ก ๋ง๋ค์ด์ง )
std::vector<int> vertex_key(V, INFINITY); // vertex์ ์ต์ weight๊ฐ ๊ณ์ฐ
std::vector<bool> selected(V, false); //์ ํ๋ vertex์ธ๊ฐ
vertex_key[start] = 0;
q.insert(II(0, start)); //์์ ๋
ธ๋ ๊ฐ์ค์น 0์ผ๋ก ์์
std::cout << "\nstart : 0\n";
/*Vertex๋งํผ ๋ฐ๋ณต*/
while (!q.empty()) {
/*extract min*/
int select_key = q.begin()->second;
int min_of_key = q.begin()->first;
q.erase(q.begin());
sum += min_of_key;
selected[select_key] = true;
std::cout << "dest : " << select_key << " (dis : " << vertex_key[select_key] << ")" << std::endl;
/*decrease key*/
for (auto e : adjList[select_key]) {
if (!selected[e.second] && vertex_key[e.second] > e.first + vertex_key[select_key]) {
q.erase({vertex_key[e.second], e.second}); //๊ฐ์ ๋
ธ๋๋ก ํฅํ๋ ๊ฐ์ ์ค weight๊ฐ ๋ ์์ ๊ฐ์ ์ด ์๋ค๋ฉด ๊ทธ ์ ๊ฐ์ ์ ์ญ์
q.insert({e.first, e.second}); //ํ์ ์ฝ์
vertex_key[e.second] = e.first + vertex_key[select_key];
}
}
}
std::cout << std::endl;
return sum;
}
int dijkstra_array(std::vector<Graph> &g, std::vector<std::vector<int>> adjMatrix, int start) {
int sum = 0;
std::vector<int> vertex_key(V, INFINITY); // vertex์ ์ต์ weight๊ฐ ๊ณ์ฐ
std::vector<bool> selected(V, false); //์ ํ๋ vertex์ธ๊ฐ
vertex_key[start] = 0;
std::cout << "\nstart : 0\n";
/*Vertex๋งํผ ๋ฐ๋ณต*/
for (int i = 0; i < V; i++) {
/*extract min*/
int select_idx = -1, min_of_key = INFINITY;
for (int j = 0; j < V; j++) {
if (!selected[j] && min_of_key > vertex_key[j]) {
select_idx = j;
min_of_key = vertex_key[j];
}
}
sum += min_of_key;
selected[select_idx] = true;
std::cout << "dest : " << select_idx << " (dis : " << vertex_key[select_idx] << ")" << std::endl;
/*decrease key*/
for (int j = 0; j < V; j++) {
if (!selected[j] && vertex_key[j] > adjMatrix[select_idx][j] + vertex_key[select_idx]) {
vertex_key[j] = adjMatrix[select_idx][j] + vertex_key[select_idx];
}
}
}
std::cout << std::endl;
return sum;
}
void make_adj_list(std::vector<Graph> g, std::vector<std::vector<II>> &adj) {
adj.resize(V);
bool isEdge;
for (int i = 0; i < g.size(); i++) {
isEdge = false;
int src = g[i].getSrc();
int dest = g[i].getDest();
int weight = g[i].getWeight();
/*๋์ผ vertex๋ก ํฅํ๋ ๊ฐ์ ์ค ๊ฐ์ฅ ์์ ๊ฐ๋ง๊ฐ์ง๊ณ ์ธ์ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค๊ธฐ ์ํ ์ฝ๋*/
if (adj[src].empty()) {
adj[src].push_back({weight, dest});
} else {
for (int j = 0; j < adj[src].size(); j++) {
if (adj[src][j].second == dest) {
isEdge = true;
if (adj[src][j].first > weight) {
adj[src][j].first = weight;
}
}
}
if (!isEdge) adj[src].push_back({weight, dest});
}
}
}
void make_adj_matrix(std::vector<Graph> g, std::vector<std::vector<int>> &adj) {
adj.assign(V, std::vector<int>(V, INFINITY));
for (int i = 0; i < g.size(); i++) {
int src = g[i].getSrc();
int dest = g[i].getDest();
int weight = g[i].getWeight();
if (adj[src][dest] > weight) {
adj[src][dest] = weight;
}
}
}
/*vertex์ ์
๋ ฅ๋ฐ์ ํ ๊ทธ๋ํ ๊ฐ์ ๊ฐ์ค์น random ์ฝ์
*/
void randomPush(std::vector<Graph> &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(Graph(i, i + 1, rand() % 1000));
for (int j = i + 1; j < V; j++) {
g.push_back(Graph(i, j, rand() % 1000));
}
}
for (int i = (rand() % 3); i < V - 1; i += (rand() % 10)) {
g.push_back(Graph(i, i + 1, rand() % 1000));
for (int j = i + 1; j < V; j += (rand() % 10)) {
g.push_back(Graph(i, j, rand() % 1000));
}
}
}
void print_edge_info(std::vector<Graph> g) {
std::cout << "edge info : \n";
std::for_each(g.begin(), g.end(), [](Graph a) {
std::cout << "src : " << a.getSrc() << " desc : " << a.getDest() << " weight : " << a.getWeight() << std::endl;
});
}
//์คํ ์๊ฐ์ ์ธก์ ๋ฐ ์ถ๋ ฅํ๋ ํจ์
void CalcTime() {
used_time = finish - start;
printf("\n*********** result **********\n time : %lf sec\n", (double)(used_time) / CLOCKS_PER_SEC);
}