25_network_flow.c

Download
c 433 lines 12.2 KB
  1/*
  2 * λ„€νŠΈμ›Œν¬ ν”Œλ‘œμš° (Network Flow)
  3 * Ford-Fulkerson, Edmonds-Karp, 이뢄 λ§€μΉ­, μ΅œμ†Œ μ»·
  4 *
  5 * κ·Έλž˜ν”„μ—μ„œ μ΅œλŒ€ μœ λŸ‰μ„ μ°ΎλŠ” μ•Œκ³ λ¦¬μ¦˜μž…λ‹ˆλ‹€.
  6 */
  7
  8#include <stdio.h>
  9#include <stdlib.h>
 10#include <string.h>
 11#include <limits.h>
 12#include <stdbool.h>
 13
 14#define MAX_V 1001
 15#define INF INT_MAX
 16
 17/* =============================================================================
 18 * 1. Ford-Fulkerson (DFS 기반)
 19 * ============================================================================= */
 20
 21int capacity_ff[MAX_V][MAX_V];
 22bool visited_ff[MAX_V];
 23
 24int dfs_ff(int u, int sink, int flow) {
 25    if (u == sink) return flow;
 26    visited_ff[u] = true;
 27
 28    for (int v = 0; v < MAX_V; v++) {
 29        if (!visited_ff[v] && capacity_ff[u][v] > 0) {
 30            int min_flow = (flow < capacity_ff[u][v]) ? flow : capacity_ff[u][v];
 31            int result = dfs_ff(v, sink, min_flow);
 32            if (result > 0) {
 33                capacity_ff[u][v] -= result;
 34                capacity_ff[v][u] += result;
 35                return result;
 36            }
 37        }
 38    }
 39    return 0;
 40}
 41
 42int ford_fulkerson(int source, int sink, int n) {
 43    int max_flow = 0;
 44    int flow;
 45
 46    while (1) {
 47        memset(visited_ff, false, sizeof(visited_ff));
 48        flow = dfs_ff(source, sink, INF);
 49        if (flow == 0) break;
 50        max_flow += flow;
 51    }
 52
 53    return max_flow;
 54}
 55
 56/* =============================================================================
 57 * 2. Edmonds-Karp (BFS 기반, O(VE²))
 58 * ============================================================================= */
 59
 60typedef struct {
 61    int** capacity;
 62    int** flow;
 63    int n;
 64} FlowNetwork;
 65
 66FlowNetwork* fn_create(int n) {
 67    FlowNetwork* fn = malloc(sizeof(FlowNetwork));
 68    fn->n = n;
 69    fn->capacity = malloc(n * sizeof(int*));
 70    fn->flow = malloc(n * sizeof(int*));
 71    for (int i = 0; i < n; i++) {
 72        fn->capacity[i] = calloc(n, sizeof(int));
 73        fn->flow[i] = calloc(n, sizeof(int));
 74    }
 75    return fn;
 76}
 77
 78void fn_free(FlowNetwork* fn) {
 79    for (int i = 0; i < fn->n; i++) {
 80        free(fn->capacity[i]);
 81        free(fn->flow[i]);
 82    }
 83    free(fn->capacity);
 84    free(fn->flow);
 85    free(fn);
 86}
 87
 88void fn_add_edge(FlowNetwork* fn, int u, int v, int cap) {
 89    fn->capacity[u][v] += cap;
 90}
 91
 92int edmonds_karp(FlowNetwork* fn, int source, int sink) {
 93    int max_flow = 0;
 94    int* parent = malloc(fn->n * sizeof(int));
 95    int* queue = malloc(fn->n * sizeof(int));
 96
 97    while (1) {
 98        memset(parent, -1, fn->n * sizeof(int));
 99        parent[source] = source;
100
101        /* BFS */
102        int front = 0, rear = 0;
103        queue[rear++] = source;
104
105        while (front < rear && parent[sink] == -1) {
106            int u = queue[front++];
107            for (int v = 0; v < fn->n; v++) {
108                if (parent[v] == -1 &&
109                    fn->capacity[u][v] - fn->flow[u][v] > 0) {
110                    parent[v] = u;
111                    queue[rear++] = v;
112                }
113            }
114        }
115
116        if (parent[sink] == -1) break;
117
118        /* 경둜 상 μ΅œμ†Œ μš©λŸ‰ μ°ΎκΈ° */
119        int path_flow = INF;
120        for (int v = sink; v != source; v = parent[v]) {
121            int u = parent[v];
122            int residual = fn->capacity[u][v] - fn->flow[u][v];
123            if (residual < path_flow) path_flow = residual;
124        }
125
126        /* μœ λŸ‰ μ—…λ°μ΄νŠΈ */
127        for (int v = sink; v != source; v = parent[v]) {
128            int u = parent[v];
129            fn->flow[u][v] += path_flow;
130            fn->flow[v][u] -= path_flow;
131        }
132
133        max_flow += path_flow;
134    }
135
136    free(parent);
137    free(queue);
138    return max_flow;
139}
140
141/* =============================================================================
142 * 3. 이뢄 λ§€μΉ­ (Bipartite Matching)
143 * ============================================================================= */
144
145typedef struct {
146    int** adj;
147    int* adj_size;
148    int* match_left;
149    int* match_right;
150    bool* visited;
151    int left_n;
152    int right_n;
153} BipartiteGraph;
154
155BipartiteGraph* bg_create(int left_n, int right_n) {
156    BipartiteGraph* bg = malloc(sizeof(BipartiteGraph));
157    bg->left_n = left_n;
158    bg->right_n = right_n;
159    bg->adj = malloc(left_n * sizeof(int*));
160    bg->adj_size = calloc(left_n, sizeof(int));
161    for (int i = 0; i < left_n; i++) {
162        bg->adj[i] = malloc(right_n * sizeof(int));
163    }
164    bg->match_left = malloc(left_n * sizeof(int));
165    bg->match_right = malloc(right_n * sizeof(int));
166    bg->visited = malloc(right_n * sizeof(bool));
167    memset(bg->match_left, -1, left_n * sizeof(int));
168    memset(bg->match_right, -1, right_n * sizeof(int));
169    return bg;
170}
171
172void bg_free(BipartiteGraph* bg) {
173    for (int i = 0; i < bg->left_n; i++) {
174        free(bg->adj[i]);
175    }
176    free(bg->adj);
177    free(bg->adj_size);
178    free(bg->match_left);
179    free(bg->match_right);
180    free(bg->visited);
181    free(bg);
182}
183
184void bg_add_edge(BipartiteGraph* bg, int left, int right) {
185    bg->adj[left][bg->adj_size[left]++] = right;
186}
187
188bool bg_dfs(BipartiteGraph* bg, int u) {
189    for (int i = 0; i < bg->adj_size[u]; i++) {
190        int v = bg->adj[u][i];
191        if (bg->visited[v]) continue;
192        bg->visited[v] = true;
193
194        if (bg->match_right[v] == -1 || bg_dfs(bg, bg->match_right[v])) {
195            bg->match_left[u] = v;
196            bg->match_right[v] = u;
197            return true;
198        }
199    }
200    return false;
201}
202
203int bipartite_matching(BipartiteGraph* bg) {
204    int matching = 0;
205
206    for (int u = 0; u < bg->left_n; u++) {
207        memset(bg->visited, false, bg->right_n * sizeof(bool));
208        if (bg_dfs(bg, u)) {
209            matching++;
210        }
211    }
212
213    return matching;
214}
215
216/* =============================================================================
217 * 4. ν˜Έν”„ν¬λ‘œν”„νŠΈ-μΉ΄ν”„ (Hopcroft-Karp, O(E√V))
218 * ============================================================================= */
219
220int* dist_hk;
221int* match_left_hk;
222int* match_right_hk;
223int** adj_hk;
224int* adj_size_hk;
225int left_n_hk, right_n_hk;
226
227bool hk_bfs(void) {
228    int* queue = malloc((left_n_hk + 1) * sizeof(int));
229    int front = 0, rear = 0;
230
231    for (int u = 0; u < left_n_hk; u++) {
232        if (match_left_hk[u] == -1) {
233            dist_hk[u] = 0;
234            queue[rear++] = u;
235        } else {
236            dist_hk[u] = INF;
237        }
238    }
239
240    bool found = false;
241    while (front < rear) {
242        int u = queue[front++];
243        for (int i = 0; i < adj_size_hk[u]; i++) {
244            int v = adj_hk[u][i];
245            int next = match_right_hk[v];
246            if (next == -1) {
247                found = true;
248            } else if (dist_hk[next] == INF) {
249                dist_hk[next] = dist_hk[u] + 1;
250                queue[rear++] = next;
251            }
252        }
253    }
254
255    free(queue);
256    return found;
257}
258
259bool hk_dfs(int u) {
260    for (int i = 0; i < adj_size_hk[u]; i++) {
261        int v = adj_hk[u][i];
262        int next = match_right_hk[v];
263        if (next == -1 || (dist_hk[next] == dist_hk[u] + 1 && hk_dfs(next))) {
264            match_left_hk[u] = v;
265            match_right_hk[v] = u;
266            return true;
267        }
268    }
269    dist_hk[u] = INF;
270    return false;
271}
272
273int hopcroft_karp(int left_n, int right_n, int** adj, int* adj_size) {
274    left_n_hk = left_n;
275    right_n_hk = right_n;
276    adj_hk = adj;
277    adj_size_hk = adj_size;
278
279    dist_hk = malloc(left_n * sizeof(int));
280    match_left_hk = malloc(left_n * sizeof(int));
281    match_right_hk = malloc(right_n * sizeof(int));
282
283    memset(match_left_hk, -1, left_n * sizeof(int));
284    memset(match_right_hk, -1, right_n * sizeof(int));
285
286    int matching = 0;
287    while (hk_bfs()) {
288        for (int u = 0; u < left_n; u++) {
289            if (match_left_hk[u] == -1 && hk_dfs(u)) {
290                matching++;
291            }
292        }
293    }
294
295    free(dist_hk);
296    free(match_left_hk);
297    free(match_right_hk);
298    return matching;
299}
300
301/* =============================================================================
302 * 5. μ΅œμ†Œ μ»· (Min Cut)
303 * ============================================================================= */
304
305void find_min_cut(FlowNetwork* fn, int source, int* reachable, int* cut_size) {
306    bool* visited = calloc(fn->n, sizeof(bool));
307    int* queue = malloc(fn->n * sizeof(int));
308    int front = 0, rear = 0;
309
310    visited[source] = true;
311    queue[rear++] = source;
312
313    *cut_size = 0;
314
315    while (front < rear) {
316        int u = queue[front++];
317        reachable[(*cut_size)++] = u;
318        for (int v = 0; v < fn->n; v++) {
319            if (!visited[v] && fn->capacity[u][v] - fn->flow[u][v] > 0) {
320                visited[v] = true;
321                queue[rear++] = v;
322            }
323        }
324    }
325
326    free(visited);
327    free(queue);
328}
329
330/* =============================================================================
331 * ν…ŒμŠ€νŠΈ
332 * ============================================================================= */
333
334int main(void) {
335    printf("============================================================\n");
336    printf("λ„€νŠΈμ›Œν¬ ν”Œλ‘œμš° 예제\n");
337    printf("============================================================\n");
338
339    /* 1. Edmonds-Karp */
340    printf("\n[1] Edmonds-Karp μ•Œκ³ λ¦¬μ¦˜\n");
341    FlowNetwork* fn = fn_create(6);
342    fn_add_edge(fn, 0, 1, 16);
343    fn_add_edge(fn, 0, 2, 13);
344    fn_add_edge(fn, 1, 2, 10);
345    fn_add_edge(fn, 1, 3, 12);
346    fn_add_edge(fn, 2, 1, 4);
347    fn_add_edge(fn, 2, 4, 14);
348    fn_add_edge(fn, 3, 2, 9);
349    fn_add_edge(fn, 3, 5, 20);
350    fn_add_edge(fn, 4, 3, 7);
351    fn_add_edge(fn, 4, 5, 4);
352
353    printf("    κ·Έλž˜ν”„:\n");
354    printf("      0 β†’ 1 (16), 0 β†’ 2 (13)\n");
355    printf("      1 β†’ 2 (10), 1 β†’ 3 (12)\n");
356    printf("      2 β†’ 1 (4),  2 β†’ 4 (14)\n");
357    printf("      3 β†’ 2 (9),  3 β†’ 5 (20)\n");
358    printf("      4 β†’ 3 (7),  4 β†’ 5 (4)\n");
359    printf("    μ΅œλŒ€ μœ λŸ‰ (0β†’5): %d\n", edmonds_karp(fn, 0, 5));
360    fn_free(fn);
361
362    /* 2. 이뢄 λ§€μΉ­ */
363    printf("\n[2] 이뢄 λ§€μΉ­\n");
364    BipartiteGraph* bg = bg_create(4, 4);
365    /* μž‘μ—…μž(0-3)와 μž‘μ—…(0-3) λ§€μΉ­ */
366    bg_add_edge(bg, 0, 0);
367    bg_add_edge(bg, 0, 1);
368    bg_add_edge(bg, 1, 0);
369    bg_add_edge(bg, 1, 2);
370    bg_add_edge(bg, 2, 1);
371    bg_add_edge(bg, 2, 2);
372    bg_add_edge(bg, 3, 2);
373    bg_add_edge(bg, 3, 3);
374
375    printf("    μž‘μ—…μž-μž‘μ—… μ—°κ²°:\n");
376    printf("      μž‘μ—…μž0: μž‘μ—…0, μž‘μ—…1\n");
377    printf("      μž‘μ—…μž1: μž‘μ—…0, μž‘μ—…2\n");
378    printf("      μž‘μ—…μž2: μž‘μ—…1, μž‘μ—…2\n");
379    printf("      μž‘μ—…μž3: μž‘μ—…2, μž‘μ—…3\n");
380    printf("    μ΅œλŒ€ λ§€μΉ­: %d\n", bipartite_matching(bg));
381
382    printf("    λ§€μΉ­ κ²°κ³Ό:\n");
383    for (int i = 0; i < bg->left_n; i++) {
384        if (bg->match_left[i] != -1) {
385            printf("      μž‘μ—…μž%d β†’ μž‘μ—…%d\n", i, bg->match_left[i]);
386        }
387    }
388    bg_free(bg);
389
390    /* 3. μ΅œμ†Œ λ²„ν…μŠ€ 컀버 */
391    printf("\n[3] μ΅œμ†Œ λ²„ν…μŠ€ 컀버 (이뢄 κ·Έλž˜ν”„)\n");
392    printf("    Konig's theorem: μ΅œλŒ€ λ§€μΉ­ = μ΅œμ†Œ λ²„ν…μŠ€ 컀버\n");
393    printf("    μœ„ 예제의 μ΅œμ†Œ λ²„ν…μŠ€ 컀버: 4\n");
394
395    /* 4. Ford-Fulkerson */
396    printf("\n[4] Ford-Fulkerson (간단 예제)\n");
397    memset(capacity_ff, 0, sizeof(capacity_ff));
398    capacity_ff[0][1] = 10;
399    capacity_ff[0][2] = 10;
400    capacity_ff[1][2] = 2;
401    capacity_ff[1][3] = 4;
402    capacity_ff[1][4] = 8;
403    capacity_ff[2][4] = 9;
404    capacity_ff[3][5] = 10;
405    capacity_ff[4][3] = 6;
406    capacity_ff[4][5] = 10;
407
408    printf("    μ΅œλŒ€ μœ λŸ‰ (0β†’5): %d\n", ford_fulkerson(0, 5, 6));
409
410    /* 5. μ‘μš© */
411    printf("\n[5] λ„€νŠΈμ›Œν¬ ν”Œλ‘œμš° μ‘μš©\n");
412    printf("    - 이뢄 λ§€μΉ­: μž‘μ—… ν• λ‹Ή, 결혼 문제\n");
413    printf("    - μ΅œμ†Œ μ»·: λ„€νŠΈμ›Œν¬ λΆ„ν• \n");
414    printf("    - μ΅œλŒ€ 독립 μ§‘ν•© (이뢄 κ·Έλž˜ν”„)\n");
415    printf("    - ν”„λ‘œμ νŠΈ 선택 문제\n");
416    printf("    - μˆœν™˜ 흐름\n");
417
418    /* 6. λ³΅μž‘λ„ */
419    printf("\n[6] λ³΅μž‘λ„\n");
420    printf("    | μ•Œκ³ λ¦¬μ¦˜         | μ‹œκ°„λ³΅μž‘λ„    |\n");
421    printf("    |------------------|---------------|\n");
422    printf("    | Ford-Fulkerson   | O(E Γ— f)      |\n");
423    printf("    | Edmonds-Karp     | O(VEΒ²)        |\n");
424    printf("    | Dinic            | O(VΒ²E)        |\n");
425    printf("    | 이뢄 λ§€μΉ­ (DFS)  | O(VE)         |\n");
426    printf("    | Hopcroft-Karp    | O(E√V)        |\n");
427    printf("    f: μ΅œλŒ€ μœ λŸ‰\n");
428
429    printf("\n============================================================\n");
430
431    return 0;
432}