3.6.3 Ford Fulkerson algorithm(ν΄λ“œν’€μ»€μŠ¨ μ•Œκ³ λ¦¬μ¦˜)

2024. 2. 6. 18:44ㆍCS - Roadmap.sh/3. Common Algorithms

CS - 3. Common Algorithms - 3.6 Greedy Algorithms - 3.6.3 Ford Fulkerson algorithm

 

Ford Fulkerson Algorithm

πŸ’‘Ford Fulkerson Algorithm is a greedy algorithm that is used to find the maximum flow in a flow network. It is also known as the Edmonds-Karp Algorithm.

ν¬λ“œ ν’€μ»€μŠ¨ μ•Œκ³ λ¦¬μ¦˜μ€ 흐름 λ„€νŠΈμ›Œν¬μ—μ„œ μ΅œλŒ€ 흐름을 μ°ΎλŠ” 데 μ‚¬μš©λ˜λŠ” νƒμš• μ•Œκ³ λ¦¬μ¦˜μž…λ‹ˆλ‹€. μ—λ“œλ¨Όμ¦ˆ-μΉ΄ν”„ μ•Œκ³ λ¦¬μ¦˜μ΄λΌκ³ λ„ ν•©λ‹ˆλ‹€.

 

 

ν¬λ“œ-ν’€μ»€μŠ¨(Ford-Fulkerson) μ•Œκ³ λ¦¬μ¦˜μ€ λ„€νŠΈμ›Œν¬ ν”Œλ‘œμš° 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•œ 방법 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€.

이 μ•Œκ³ λ¦¬μ¦˜μ€ μ†ŒμŠ€ λ…Έλ“œμ—μ„œ νƒ€κ²Ÿ λ…Έλ“œλ‘œμ˜ μ΅œλŒ€ ν”Œλ‘œμš°λ₯Ό μ°ΎλŠ” 문제λ₯Ό ν•΄κ²°ν•©λ‹ˆλ‹€.

이λ₯Ό μœ„ν•΄, '증가 경둜(augmenting path)'λ₯Ό μ΄μš©ν•˜λŠ”λ°, 증가 κ²½λ‘œλž€ μ†ŒμŠ€μ—μ„œ νƒ€κ²ŸμœΌλ‘œ μ΄μ–΄μ§€λŠ” 경둜 쀑 아직 더 λ§Žμ€ ν”Œλ‘œμš°λ₯Ό ν†΅κ³Όμ‹œν‚¬ 수 μžˆλŠ” 경둜λ₯Ό λ§ν•©λ‹ˆλ‹€.

 

Ford Fulkerson μ•Œκ³ λ¦¬μ¦˜μ˜ λ™μž‘ μ›λ¦¬λŠ” μ΄λ ‡μŠ΅λ‹ˆλ‹€.
1. λͺ¨λ“  κ°„μ„ μ˜ ν”Œλ‘œμš°λ₯Ό 0으둜 μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
2. 증가 κ²½λ‘œκ°€ μ‘΄μž¬ν•˜λŠ” λ™μ•ˆ λ‹€μŒμ˜ μž‘μ—…μ„ λ°˜λ³΅ν•©λ‹ˆλ‹€.
3. 증가 κ²½λ‘œμ— λŒ€ν•œ μ΅œμ†Œ μž”μ—¬ μš©λŸ‰μ„ μ°ΎμŠ΅λ‹ˆλ‹€.
4. κ·Έ κ²½λ‘œμ— λŒ€ν•΄ μ΅œμ†Œ μž”μ—¬ μš©λŸ‰λ§ŒνΌ ν”Œλ‘œμš°λ₯Ό μ¦κ°€μ‹œν‚΅λ‹ˆλ‹€.
이 κ³Όμ •μ„ λ°˜λ³΅ν•˜λ©΄μ„œ μ†ŒμŠ€μ—μ„œ νƒ€κ²ŸμœΌλ‘œμ˜ ν”Œλ‘œμš°λ₯Ό μ΅œλŒ€λ‘œ λ§Œλ“œλŠ” κ²ƒμ΄ Ford-Fulkerson μ•Œκ³ λ¦¬μ¦˜μ˜ λͺ©ν‘œμž…λ‹ˆλ‹€.

 

In Python
from collections import defaultdict 

class Graph: 

    def __init__(self, vertices): 
        self.verts = vertices   # κ·Έλž˜ν”„μ˜ 정점 수λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.
        self.graph = [[0 for column in range(vertices)] for row in range(vertices)]   # 2차원 배열을 μ‚¬μš©ν•˜μ—¬ κ·Έλž˜ν”„λ₯Ό λ‚˜νƒ€λƒ…λ‹ˆλ‹€.

    # λ„ˆλΉ„ μš°μ„  탐색(BFS)을 톡해 μ†ŒμŠ€μ—μ„œ νƒ€κ²ŸμœΌλ‘œ μ΄μ–΄μ§€λŠ” κ²½λ‘œκ°€ μžˆλŠ”μ§€ ν™•μΈν•©λ‹ˆλ‹€.
    def BFS(self, s, t, parent): 
        visited =[False]*(self.verts)  # λͺ¨λ“  정점을 λ°©λ¬Έν•˜μ§€ μ•Šμ€ μƒνƒœλ‘œ μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
        queue=[] 
        queue.append(s)  # μ†ŒμŠ€λ₯Ό 큐에 μΆ”κ°€ν•©λ‹ˆλ‹€.
        visited[s] = True  # μ†ŒμŠ€λ₯Ό λ°©λ¬Έν•œ μƒνƒœλ‘œ ν‘œμ‹œν•©λ‹ˆλ‹€.

        while queue: 
            u = queue.pop(0) 

            for ind, val in enumerate(self.graph[u]): 
                if visited[ind] == False and val > 0 :   # λ°©λ¬Έν•˜μ§€ μ•Šμ€ 정점과 μš©λŸ‰μ΄ 0보닀 큰 경둜λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.
                    queue.append(ind)  # 찾은 정점을 큐에 μΆ”κ°€ν•©λ‹ˆλ‹€.
                    visited[ind] = True  # 찾은 정점을 λ°©λ¬Έν•œ μƒνƒœλ‘œ ν‘œμ‹œν•©λ‹ˆλ‹€.
                    parent[ind] = u  # ν•΄λ‹Ή μ •μ μ˜ λΆ€λͺ¨λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.

        return True if visited[t] else False  # νƒ€κ²Ÿμ„ λ°©λ¬Έν–ˆλ‹€λ©΄ Trueλ₯Ό, λ°©λ¬Έν•˜μ§€ μ•Šμ•˜λ‹€λ©΄ Falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

    # μ†ŒμŠ€μ—μ„œ νƒ€κ²ŸμœΌλ‘œμ˜ μ΅œλŒ€ ν”Œλ‘œμš°λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€.
    def FordFulkerson(self, source, sink): 
        parent = [-1]*(self.verts)  # λΆ€λͺ¨λ₯Ό μ €μž₯ν•˜λŠ” 리슀트λ₯Ό μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
        max_flow = 0  # μ΅œλŒ€ ν”Œλ‘œμš°λ₯Ό 0으둜 μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.

        while self.BFS(source, sink, parent) :  # BFSλ₯Ό μ‚¬μš©ν•˜μ—¬ 증가 경둜λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.
            path_flow = float("Inf")  # 경둜의 ν”Œλ‘œμš°λ₯Ό λ¬΄ν•œλŒ€λ‘œ μ΄ˆκΈ°ν™”ν•©λ‹ˆλ‹€.
            s = sink 
            while(s != source): 
                path_flow = min (path_flow, self.graph[parent[s]][s])  # 경둜의 μ΅œμ†Œ μš©λŸ‰μ„ μ°ΎμŠ΅λ‹ˆλ‹€.
                s = parent[s] 

            max_flow += path_flow  # μ΅œλŒ€ ν”Œλ‘œμš°μ— 경둜의 μ΅œμ†Œ μš©λŸ‰μ„ λ”ν•©λ‹ˆλ‹€.

            v = sink 
            while(v != source): 
                u = parent[v] 
                self.graph[u][v] -= path_flow  # μ •λ°©ν–₯ κ°„μ„ μ˜ μš©λŸ‰μ„ μ€„μž…λ‹ˆλ‹€.
                self.graph[v][u] += path_flow  # μ—­λ°©ν–₯ κ°„μ„ μ˜ μš©λŸ‰μ„ λŠ˜λ¦½λ‹ˆλ‹€.
                v = parent[v] 

        return max_flow  # μ΅œλŒ€ ν”Œλ‘œμš°λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

 

g.graph = [[0, 3, 2, 0, 0], 
           [0, 0, 1, 2, 0], 
           [0, 0, 0, 0, 2], 
           [0, 0, 0, 0, 3], 
           [0, 0, 0, 0, 0]]

이런 κ·Έλž˜ν”„λ₯Ό μ˜ˆμ‹œλ‘œ λ“€κ² μŠ΅λ‹ˆλ‹€.

 

 

0번 λ…Έλ“œμ—μ„œ 4λ²ˆλ…Έλ“œκ°€ νƒ€κ²ŸμΌλ•Œ μ΅œλŒ€ ν”Œλ‘œμš°λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€.

ν΄λ“œ-ν’€μ»€μŠ¨ μ•Œκ³ λ¦¬μ¦˜μ˜ μž‘λ™ κ³Όμ •λŒ€λ‘œ 따라가 λ³΄κ² μŠ΅λ‹ˆλ‹€.

1. 초기의 λͺ¨λ“  ν”Œλ‘œμš°λŠ” 0

2. 증가 경둜λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€. 

 0-1-3-4 λ˜λŠ” 0-2-4 μž…λ‹ˆλ‹€.

3. μ¦κ°€κ²½λ‘œμ—μ„œ κ°€μž₯ μž‘μ€ μš©λŸ‰μ„ μ°ΎμŠ΅λ‹ˆλ‹€.

이 값이 이 경둜λ₯Ό 톡해 흘러갈 수 μžˆλŠ” ν”Œλ‘œμš°μ˜ μ–‘μž…λ‹ˆλ‹€.

예둜, 0-1-3-4 라면, 이 경둜의 κ°„μ„ μ˜ μš©λŸ‰μ€ 각각 3,2,3 μ΄λ―€λ‘œ κ°€μž₯ μž‘μ€ 값인 2κ°€ 이 경둜λ₯Ό 톡해 흘러갈 ν”Œλ‘œμš°μ˜ 양이 λ©λ‹ˆλ‹€.

4. 이 ν”Œλ‘œμš°λ₯Ό 총 ν”Œλ‘œμš°μ— λ”ν•˜κ³ , 이 ν”Œλ‘œμš°λ§ŒνΌ 각 κ°„μ„ μ˜ μš©λŸ‰μ„ μ€„μž…λ‹ˆλ‹€.

μœ„ μ˜ˆμ‹œμ˜ 경우, μ΄ν”Œλ‘œμš°λŠ” 2κ°€ 되고, κ°„μ„ μ˜ μš©λŸ‰μ€ (0-1 :1), (1-3 : 0), (3-4 : 1)이 λ©λ‹ˆλ‹€.

5. 이 과정을 증가 κ²½λ‘œκ°€ 없을 λ•ŒκΉŒμ§€ λ°˜λ³΅ν•©λ‹ˆλ‹€.

 

λ”°λΌμ„œ 0λ…Έλ“œμ—μ„œ 4λ…Έλ“œ κΉŒμ§€ 흘러갈 수 μžˆλŠ”  μ΅œλŒ€ ν”Œλ‘œμš°κ°€ 4μž…λ‹ˆλ‹€.

 

ν™œμš©

 

ν΄λ“œ-ν’€μ»€μŠ¨ μ•Œκ³ λ¦¬μ¦˜μ€ 주둜 'λ„€νŠΈμ›Œν¬ ν”Œλ‘œμš°' λ¬Έμ œμ— ν™œμš©λ©λ‹ˆλ‹€.

 

1. ꡐ톡, λ¬Όλ₯˜ λ„€νŠΈμ›Œν¬ μ΅œμ ν™”

2. 톡신 λ„€νŠΈμ›Œν¬

3. μžμ› ν• λ‹Ή

4. 이미지 μ„ΈλΆ„ν™”

이미지 μ²˜λ¦¬μ—μ„œ 각 픽셀을 λ…Έλ“œλ‘œ μƒκ°ν•˜κ³  인접 ν”½μ…€κ°„μ˜ 연결을 κ°„μ„ μœΌλ‘œ μƒκ°ν•˜μ—¬ 이미지λ₯Ό μ—¬λŸ¬ μ˜μ—­μœΌλ‘œ λ‚˜λˆ  λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

 

 

 

μ°Έκ³ 

https://ratsgo.github.io/data%20structure&algorithm/2017/11/29/maxflow/

 

μ΅œλŒ€ μœ λŸ‰ μ•Œκ³ λ¦¬μ¦˜ (1) · ratsgo's blog

이번 κΈ€μ—μ„œλŠ” μ΅œλŒ€ μœ λŸ‰ μ•Œκ³ λ¦¬μ¦˜(Max Flow Algorithm)을 ν¬λ“œ-ν’€μ»€μŠ¨ μ•Œκ³ λ¦¬μ¦˜(Ford-Fulkerson Algorithm)을 μ€‘μ‹¬μœΌλ‘œ μ‚΄νŽ΄λ³΄λ„λ‘ ν•˜κ² μŠ΅λ‹ˆλ‹€. 이 글은 κ³ λ €λŒ€ κΉ€μ„ μš± κ΅μˆ˜λ‹˜κ³Ό μ—­μ‹œ 같은 λŒ€ν•™μ˜ 김황남 ꡐ

ratsgo.github.io

 

728x90