JMK no matter what

NetworkFlow class

lang:cpp
#include<queue>
#include<cstdlib>
#include<vector>
#include<cassert>

using namespace std;

// Edmonds-Karp 네트워크 플로우 알고리즘의 구현. 원저자: JongMan
// 시간 복잡도: O(V*E*E)
// 공간 복잡도: O(V*V)
// 주의
//  1. 이 클래스는 반드시 힙에 선언할 것! 클래스 크기가 크므로 스택에 선언하면 
//     스택 오버플로우가 날 수 있다.
//  2. MAXV 가 실제 정점 개수와 같거나 그보다 큰지 반드시 확인할 것.
class NetworkFlow
{
    public:

        // 내부 함수 및 변수
        // =================
        // MAXV 는 최대 정점의 수
        enum { MAXV = 210 };        
        int flow[MAXV][MAXV], cap[MAXV][MAXV], totalFlow, V;
        // (a, b) 간선으로 c 만큼의 유량을 보낸다
        void push(int a, int b, int c) { flow[a][b] += c; flow[b][a] = - flow[a][b]; }
        // (a, b) 간선의 residual capacity 를 반환한다
        int res(int a, int b) { return cap[a][b] - flow[a][b]; }

        // 인터페이스
        // ==========

        // V 는 정점의 최대 수
        NetworkFlow(int V): V(V) 
        { 
            assert(V <= MAXV); 
            memset(flow, 0, sizeof(flow)); 
            memset(cap, 0, sizeof(cap)); 
            totalFlow = 0; 
        }
        // (a, b) 간선의 capacity 에 c 를 더한다
        void addEdge(int a, int b, int c) { cap[a][b] += c; }
        // source 로부터 sink 까지 한 번 augmenting path 를 찾아 보내고, 이 path 의 유량을 반환한다
        int pushFlow(int source, int sink)
        {
            vector<int> pred(V, -1); queue<int> q;
            q.push(source); pred[source] = source;
            while(!q.empty() && pred[sink] == -1)
            {
                int u = q.front(); q.pop();
                for(int v = 0; v < V; ++v) if(res(u,v) > 0 && pred[v] == -1) { pred[v] = u; q.push(v); }
            }
            if(pred[sink] == -1) return 0;
            int h, amt = 2147483647;
            h = sink; while(pred[h] != h) { amt = min(amt, res(pred[h], h)); h = pred[h]; }
            h = sink; while(pred[h] != h) { push(pred[h], h, amt); h = pred[h]; }
            totalFlow += amt;
            return amt;
        }
        // source 로부터 sink 까지의 최대 유량을 반환한다
        int go(int source = 0, int sink = 1)
        {
            int ret = 0, f;
            while(f = pushFlow(source, sink))
                ret += f;
            return ret;
        }
};

int main()
{
    NetworkFlow* flow = new NetworkFlow(3);
    flow->addEdge(0, 1, 7);
    flow->addEdge(1, 2, 4);
    assert(flow->go(0, 2) == 4);
    delete flow;
}
2009-02-24 01:45:53 | JM | /logs/library/ | 0 Comments

Leave a comment