record logo record

네트워크 플로우(Network Flow) 란?

네트워크 플로우(Network Flow) 알고리즘의 특징

네트워크 플로우(Network Flow)의 알고리즘 예시

최종적으로 최대 유량은 19 만큼 흐르게 되는것을 알 수 있다.

Source Code

#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

#define MAX 100
#define INF 1000000000

using namespace std;

int n = 6, result;
// c 용량 ,f 유량 ,d 특정 노드를 방문했는지 
int c[MAX][MAX], f[MAX][MAX], d[MAX];
// 특정 노드에 연결된 간선 
vector<int> a[MAX];
// 최대 유량을 구하는 함수 
void maxFlow(int start, int end) {
	while(1) {
		
		fill(d, d + MAX, -1); // 모든 정점은 방문하지 않은 상태로 초기화 
		queue<int> q;
		q.push(start);
		while(!q.empty()) {
			int x = q.front();
			q.pop();
			for(int i = 0; i < a[x].size(); i++) {
				int y = a[x][i];
				// 방문하지 않은 노드 중에서 용량이 남은 경우
				if(c[x][y] - f[x][y] > 0 && d[y] == -1) {
					q.push(y);
					d[y] = x; // 경로를 기억합니다.
					if(y == end) break; // 도착지에 도달을 한 경우 
				} 
			}
		}
		// 모든 경로를 다 찾은 뒤에 탈출한다. 
		if(d[end] == -1) break;
		int flow = INF; // 최소값을 찾으려고
		// 거꾸로 최소 유량을 탐색한다. 
		for(int i = end; i != start; i = d[i]){
			flow = min(flow, c[d[i]][i] - f[d[i]][i]);
		} 
		// 최소 유량 만큼 추가한다.
		for(int i = end; i != start; i = d[i]){
			f[d[i]][i] += flow;
			f[i][d[i]] -= flow;
			
		}
		result += flow; 
	}
}

int main (void) {
	a[1].push_back(2);
	a[2].push_back(1);
	c[1][2] = 12;
	
	a[1].push_back(4);
	a[4].push_back(1);
	c[1][4] = 11;
	
	a[2].push_back(3);
	a[3].push_back(2);
	c[2][3] = 6;
	
	a[2].push_back(4);
	a[4].push_back(2);
	c[2][4] = 3;
	
	a[2].push_back(5);
	a[5].push_back(2);
	c[2][5] = 5;
	
	a[2].push_back(6);
	a[6].push_back(2);
	c[2][6] = 9;
	
	a[3].push_back(6);
	a[6].push_back(3);
	c[3][6] = 8;

	a[4].push_back(5);
	a[5].push_back(4);
	c[4][5] = 9;

	a[5].push_back(3);
	a[3].push_back(5);
	c[5][3] = 3;
	
	a[5].push_back(6);
	a[6].push_back(5);
	c[5][6] = 4;
	
	maxFlow(1, 6);
	printf("%d", result);
}

실제로 네트워크 플로우 알고리즘의 경우에 에드몬드 카프 알고리즘보다 빠른 알고리즘이 존재한다.
추후 이분 매칭 알고리즘 등 다양한 알고리즘으로 확장 될 수 있으므로 중요한 알고리즘이다.

네트워크 플로우(Network Flow)의 시간복잡도

BFS를 이용하는 에드몬드 카프 알고리즘의 시간 복잡도는 O(V * E^2) 이다.

References