1/*
2 * ์ต์ ์ ์ฅ ํธ๋ฆฌ (Minimum Spanning Tree)
3 * Kruskal, Prim, Union-Find
4 *
5 * ๊ทธ๋ํ์ ๋ชจ๋ ์ ์ ์ ์ฐ๊ฒฐํ๋ ์ต์ ๊ฐ์ค์น ํธ๋ฆฌ์
๋๋ค.
6 */
7
8#include <stdio.h>
9#include <stdlib.h>
10#include <limits.h>
11#include <stdbool.h>
12
13#define INF INT_MAX
14
15/* =============================================================================
16 * 1. Union-Find (Disjoint Set Union)
17 * ============================================================================= */
18
19typedef struct {
20 int* parent;
21 int* rank;
22 int size;
23} UnionFind;
24
25UnionFind* uf_create(int n) {
26 UnionFind* uf = malloc(sizeof(UnionFind));
27 uf->parent = malloc(n * sizeof(int));
28 uf->rank = calloc(n, sizeof(int));
29 uf->size = n;
30
31 for (int i = 0; i < n; i++)
32 uf->parent[i] = i;
33
34 return uf;
35}
36
37void uf_free(UnionFind* uf) {
38 free(uf->parent);
39 free(uf->rank);
40 free(uf);
41}
42
43int uf_find(UnionFind* uf, int x) {
44 if (uf->parent[x] != x)
45 uf->parent[x] = uf_find(uf, uf->parent[x]); /* ๊ฒฝ๋ก ์์ถ */
46 return uf->parent[x];
47}
48
49bool uf_union(UnionFind* uf, int x, int y) {
50 int px = uf_find(uf, x);
51 int py = uf_find(uf, y);
52
53 if (px == py) return false;
54
55 /* ๋ญํฌ ๊ธฐ๋ฐ ํฉ์น๊ธฐ */
56 if (uf->rank[px] < uf->rank[py]) {
57 uf->parent[px] = py;
58 } else if (uf->rank[px] > uf->rank[py]) {
59 uf->parent[py] = px;
60 } else {
61 uf->parent[py] = px;
62 uf->rank[px]++;
63 }
64
65 return true;
66}
67
68bool uf_connected(UnionFind* uf, int x, int y) {
69 return uf_find(uf, x) == uf_find(uf, y);
70}
71
72/* =============================================================================
73 * 2. ๊ฐ์ ๊ตฌ์กฐ์ฒด
74 * ============================================================================= */
75
76typedef struct {
77 int src;
78 int dest;
79 int weight;
80} Edge;
81
82int compare_edges(const void* a, const void* b) {
83 return ((Edge*)a)->weight - ((Edge*)b)->weight;
84}
85
86/* =============================================================================
87 * 3. ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ
88 * ============================================================================= */
89
90typedef struct {
91 Edge* edges;
92 int num_edges;
93 int total_weight;
94} MST;
95
96MST kruskal(int vertices, Edge edges[], int num_edges) {
97 /* ๊ฐ์ ์ ๊ฐ์ค์น ์์ผ๋ก ์ ๋ ฌ */
98 qsort(edges, num_edges, sizeof(Edge), compare_edges);
99
100 UnionFind* uf = uf_create(vertices);
101 MST mst;
102 mst.edges = malloc((vertices - 1) * sizeof(Edge));
103 mst.num_edges = 0;
104 mst.total_weight = 0;
105
106 for (int i = 0; i < num_edges && mst.num_edges < vertices - 1; i++) {
107 int u = edges[i].src;
108 int v = edges[i].dest;
109
110 if (uf_union(uf, u, v)) {
111 mst.edges[mst.num_edges++] = edges[i];
112 mst.total_weight += edges[i].weight;
113 }
114 }
115
116 uf_free(uf);
117 return mst;
118}
119
120/* =============================================================================
121 * 4. ํ๋ฆผ ์๊ณ ๋ฆฌ์ฆ (๋ฐฐ์ด ๊ธฐ๋ฐ)
122 * ============================================================================= */
123
124MST prim_array(int** graph, int vertices) {
125 int* key = malloc(vertices * sizeof(int)); /* ์ต์ ๊ฐ์ค์น */
126 int* parent = malloc(vertices * sizeof(int)); /* MST์์์ ๋ถ๋ชจ */
127 bool* in_mst = calloc(vertices, sizeof(bool));
128
129 for (int i = 0; i < vertices; i++) {
130 key[i] = INF;
131 parent[i] = -1;
132 }
133
134 key[0] = 0;
135
136 for (int count = 0; count < vertices - 1; count++) {
137 /* ์ต์ key ์ ์ ์ฐพ๊ธฐ */
138 int min_key = INF, u = -1;
139 for (int v = 0; v < vertices; v++) {
140 if (!in_mst[v] && key[v] < min_key) {
141 min_key = key[v];
142 u = v;
143 }
144 }
145
146 if (u == -1) break;
147 in_mst[u] = true;
148
149 /* ์ธ์ ์ ์ ๊ฐฑ์ */
150 for (int v = 0; v < vertices; v++) {
151 if (graph[u][v] && !in_mst[v] && graph[u][v] < key[v]) {
152 parent[v] = u;
153 key[v] = graph[u][v];
154 }
155 }
156 }
157
158 /* MST ๊ตฌ์ฑ */
159 MST mst;
160 mst.edges = malloc((vertices - 1) * sizeof(Edge));
161 mst.num_edges = 0;
162 mst.total_weight = 0;
163
164 for (int i = 1; i < vertices; i++) {
165 if (parent[i] != -1) {
166 mst.edges[mst.num_edges].src = parent[i];
167 mst.edges[mst.num_edges].dest = i;
168 mst.edges[mst.num_edges].weight = graph[parent[i]][i];
169 mst.total_weight += graph[parent[i]][i];
170 mst.num_edges++;
171 }
172 }
173
174 free(key);
175 free(parent);
176 free(in_mst);
177 return mst;
178}
179
180/* =============================================================================
181 * 5. ํ๋ฆผ ์๊ณ ๋ฆฌ์ฆ (์ฐ์ ์์ ํ)
182 * ============================================================================= */
183
184typedef struct {
185 int vertex;
186 int key;
187} PQNode;
188
189typedef struct {
190 PQNode* data;
191 int size;
192 int capacity;
193} PriorityQueue;
194
195PriorityQueue* pq_create(int capacity) {
196 PriorityQueue* pq = malloc(sizeof(PriorityQueue));
197 pq->data = malloc(capacity * sizeof(PQNode));
198 pq->size = 0;
199 pq->capacity = capacity;
200 return pq;
201}
202
203void pq_push(PriorityQueue* pq, int vertex, int key) {
204 int i = pq->size++;
205 pq->data[i].vertex = vertex;
206 pq->data[i].key = key;
207
208 while (i > 0) {
209 int parent = (i - 1) / 2;
210 if (pq->data[parent].key <= pq->data[i].key) break;
211 PQNode temp = pq->data[parent];
212 pq->data[parent] = pq->data[i];
213 pq->data[i] = temp;
214 i = parent;
215 }
216}
217
218PQNode pq_pop(PriorityQueue* pq) {
219 PQNode min = pq->data[0];
220 pq->data[0] = pq->data[--pq->size];
221
222 int i = 0;
223 while (2 * i + 1 < pq->size) {
224 int smallest = i;
225 int left = 2 * i + 1;
226 int right = 2 * i + 2;
227
228 if (pq->data[left].key < pq->data[smallest].key)
229 smallest = left;
230 if (right < pq->size && pq->data[right].key < pq->data[smallest].key)
231 smallest = right;
232
233 if (smallest == i) break;
234
235 PQNode temp = pq->data[i];
236 pq->data[i] = pq->data[smallest];
237 pq->data[smallest] = temp;
238 i = smallest;
239 }
240
241 return min;
242}
243
244/* ์ธ์ ๋ฆฌ์คํธ์ฉ ๊ตฌ์กฐ์ฒด */
245typedef struct AdjNode {
246 int dest;
247 int weight;
248 struct AdjNode* next;
249} AdjNode;
250
251MST prim_heap(AdjNode** adj, int vertices) {
252 int* key = malloc(vertices * sizeof(int));
253 int* parent = malloc(vertices * sizeof(int));
254 bool* in_mst = calloc(vertices, sizeof(bool));
255
256 for (int i = 0; i < vertices; i++) {
257 key[i] = INF;
258 parent[i] = -1;
259 }
260
261 PriorityQueue* pq = pq_create(vertices * vertices);
262 key[0] = 0;
263 pq_push(pq, 0, 0);
264
265 while (pq->size > 0) {
266 PQNode node = pq_pop(pq);
267 int u = node.vertex;
268
269 if (in_mst[u]) continue;
270 in_mst[u] = true;
271
272 AdjNode* neighbor = adj[u];
273 while (neighbor) {
274 int v = neighbor->dest;
275 int w = neighbor->weight;
276
277 if (!in_mst[v] && w < key[v]) {
278 key[v] = w;
279 parent[v] = u;
280 pq_push(pq, v, w);
281 }
282 neighbor = neighbor->next;
283 }
284 }
285
286 MST mst;
287 mst.edges = malloc((vertices - 1) * sizeof(Edge));
288 mst.num_edges = 0;
289 mst.total_weight = 0;
290
291 for (int i = 1; i < vertices; i++) {
292 if (parent[i] != -1) {
293 mst.edges[mst.num_edges].src = parent[i];
294 mst.edges[mst.num_edges].dest = i;
295 mst.edges[mst.num_edges].weight = key[i];
296 mst.total_weight += key[i];
297 mst.num_edges++;
298 }
299 }
300
301 free(key);
302 free(parent);
303 free(in_mst);
304 free(pq->data);
305 free(pq);
306 return mst;
307}
308
309/* =============================================================================
310 * 6. Union-Find ์์ฉ: ์ฐ๊ฒฐ ์์
311 * ============================================================================= */
312
313int count_components(int n, int edges[][2], int num_edges) {
314 UnionFind* uf = uf_create(n);
315
316 for (int i = 0; i < num_edges; i++) {
317 uf_union(uf, edges[i][0], edges[i][1]);
318 }
319
320 int count = 0;
321 for (int i = 0; i < n; i++) {
322 if (uf->parent[i] == i) count++;
323 }
324
325 uf_free(uf);
326 return count;
327}
328
329/* =============================================================================
330 * ํ
์คํธ
331 * ============================================================================= */
332
333int main(void) {
334 printf("============================================================\n");
335 printf("์ต์ ์ ์ฅ ํธ๋ฆฌ (MST) ์์ \n");
336 printf("============================================================\n");
337
338 /* 1. Union-Find */
339 printf("\n[1] Union-Find ๊ธฐ๋ณธ\n");
340 UnionFind* uf = uf_create(6);
341 printf(" union(0, 1): %s\n", uf_union(uf, 0, 1) ? "ํฉ์นจ" : "์ด๋ฏธ ์ฐ๊ฒฐ๋จ");
342 printf(" union(2, 3): %s\n", uf_union(uf, 2, 3) ? "ํฉ์นจ" : "์ด๋ฏธ ์ฐ๊ฒฐ๋จ");
343 printf(" union(1, 2): %s\n", uf_union(uf, 1, 2) ? "ํฉ์นจ" : "์ด๋ฏธ ์ฐ๊ฒฐ๋จ");
344 printf(" connected(0, 3): %s\n", uf_connected(uf, 0, 3) ? "์" : "์๋์ค");
345 printf(" connected(0, 5): %s\n", uf_connected(uf, 0, 5) ? "์" : "์๋์ค");
346 uf_free(uf);
347
348 /* 2. ํฌ๋ฃจ์ค์นผ */
349 printf("\n[2] ํฌ๋ฃจ์ค์นผ ์๊ณ ๋ฆฌ์ฆ\n");
350 Edge edges[] = {
351 {0, 1, 4}, {0, 7, 8}, {1, 2, 8}, {1, 7, 11},
352 {2, 3, 7}, {2, 8, 2}, {2, 5, 4}, {3, 4, 9},
353 {3, 5, 14}, {4, 5, 10}, {5, 6, 2}, {6, 7, 1},
354 {6, 8, 6}, {7, 8, 7}
355 };
356
357 printf(" ๊ฐ์ ์: 14, ์ ์ ์: 9\n");
358 MST mst1 = kruskal(9, edges, 14);
359 printf(" MST ๊ฐ์ :\n");
360 for (int i = 0; i < mst1.num_edges; i++) {
361 printf(" %d - %d (๊ฐ์ค์น %d)\n",
362 mst1.edges[i].src, mst1.edges[i].dest, mst1.edges[i].weight);
363 }
364 printf(" ์ด ๊ฐ์ค์น: %d\n", mst1.total_weight);
365 free(mst1.edges);
366
367 /* 3. ํ๋ฆผ (๋ฐฐ์ด) */
368 printf("\n[3] ํ๋ฆผ ์๊ณ ๋ฆฌ์ฆ (๋ฐฐ์ด)\n");
369 int** graph = malloc(5 * sizeof(int*));
370 for (int i = 0; i < 5; i++) {
371 graph[i] = calloc(5, sizeof(int));
372 }
373 graph[0][1] = graph[1][0] = 2;
374 graph[0][3] = graph[3][0] = 6;
375 graph[1][2] = graph[2][1] = 3;
376 graph[1][3] = graph[3][1] = 8;
377 graph[1][4] = graph[4][1] = 5;
378 graph[2][4] = graph[4][2] = 7;
379 graph[3][4] = graph[4][3] = 9;
380
381 MST mst2 = prim_array(graph, 5);
382 printf(" MST ๊ฐ์ :\n");
383 for (int i = 0; i < mst2.num_edges; i++) {
384 printf(" %d - %d (๊ฐ์ค์น %d)\n",
385 mst2.edges[i].src, mst2.edges[i].dest, mst2.edges[i].weight);
386 }
387 printf(" ์ด ๊ฐ์ค์น: %d\n", mst2.total_weight);
388 free(mst2.edges);
389
390 for (int i = 0; i < 5; i++) free(graph[i]);
391 free(graph);
392
393 /* 4. ์ฐ๊ฒฐ ์์ ๊ฐ์ */
394 printf("\n[4] ์ฐ๊ฒฐ ์์ ๊ฐ์\n");
395 int comp_edges[][2] = {{0, 1}, {1, 2}, {3, 4}};
396 printf(" ์ ์ : 0-4, ๊ฐ์ : (0,1), (1,2), (3,4)\n");
397 printf(" ์ฐ๊ฒฐ ์์ ๊ฐ์: %d\n", count_components(5, comp_edges, 3));
398
399 /* 5. ์๊ณ ๋ฆฌ์ฆ ๋น๊ต */
400 printf("\n[5] ์๊ณ ๋ฆฌ์ฆ ๋น๊ต\n");
401 printf(" | ์๊ณ ๋ฆฌ์ฆ | ์๊ฐ๋ณต์ก๋ | ์ ํฉํ ๊ทธ๋ํ |\n");
402 printf(" |---------------|---------------|---------------|\n");
403 printf(" | ํฌ๋ฃจ์ค์นผ | O(E log E) | ํฌ์ ๊ทธ๋ํ |\n");
404 printf(" | ํ๋ฆผ(๋ฐฐ์ด) | O(Vยฒ) | ๋ฐ์ง ๊ทธ๋ํ |\n");
405 printf(" | ํ๋ฆผ(ํ) | O(E log V) | ํฌ์ ๊ทธ๋ํ |\n");
406
407 /* 6. Union-Find ๋ณต์ก๋ */
408 printf("\n[6] Union-Find ๋ณต์ก๋\n");
409 printf(" | ์ฐ์ฐ | ์๊ฐ๋ณต์ก๋ |\n");
410 printf(" |----------|----------------|\n");
411 printf(" | find | O(ฮฑ(n)) โ O(1) |\n");
412 printf(" | union | O(ฮฑ(n)) โ O(1) |\n");
413 printf(" | ฮฑ(n): ์ญ์์ปค๋ง ํจ์ (๋งค์ฐ ๋๋ฆฌ๊ฒ ์ฆ๊ฐ)\n");
414
415 printf("\n============================================================\n");
416
417 return 0;
418}