Cod sursa(job #1393603)

Utilizator rootsroots1 roots Data 19 martie 2015 16:55:41
Problema Flux maxim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.91 kb
#include <stdio.h>
#include <vector>
#include <queue>

#define MAXN 1001

using namespace std;

int V, E;   // V = vertices, E = edges
vector <int> Gf[MAXN];  // Gf = residual network of G
int c[MAXN][MAXN];  // c = capacity on G
int s, t;   // s = source, t = sink
int f1[MAXN][MAXN]; // f1 = flow on Gf
int father[MAXN];

inline void readAndBuild() {
    scanf("%d%d", &V, &E);
    s = 1;
    t = V;
    
    int x, y, z;
    for (int e = 0; e < E; ++ e) {
        scanf("%d%d%d", &x, &y, &z);
        
        // in theory if (x, y) in E then (y, x) not in E
        // thus either c[x][y] or c[y][x] should be 0
        // in practice, both can be different than 0
        if (c[y][x] == 0) {
            Gf[x].push_back(y);
            c[x][y] = z;
            
            Gf[y].push_back(x);
        } else {
            c[x][y] = z;
        }
    }
}

inline bool bfs() {
    queue <int> q;
    q.push(s);
    
    for (int i = 1; i <= V; ++ i) {
        father[i] = 0;
    }
    
    for (int node = q.front(); !q.empty(); node = q.front()) {
        q.pop();
        
        if (node == t) {
            return true;
        }
        
        for (vector <int>::iterator it = Gf[node].begin(); it != Gf[node].end(); ++ it) {
            // f1 is the already existent flow
            // theoretically, it should be compared with cf (the capacity on Gf) and not c
            // and also the flow is always a nonnegative value
            // however, in practice we can shift the pair (f1, cf)
            // from (0, f) to (-f, 0) having the same effect
            // (notice that here cf[edge] = f[reverse edge] if edge not in E)
            if (!father[*it] && f1[node][*it] < c[node][*it]) {
                father[*it] = node;
                q.push(*it);
            }
        }
    }
    
    return false;
}

inline int maxFlowEdmondsKarpWithHacks() {
    int maxFlow = 0;
    
    for (int isPath = bfs(); isPath; isPath = bfs()) {
        // cfpath = the maximum flow that can be pushed on an augmenting path
        int cfpath = c[father[t]][t] - f1[father[t]][t];
        
        for (int node = father[t]; node != s; node = father[node]) {
            if (cfpath > c[father[node]][node] - f1[father[node]][node]) {
                cfpath = c[father[node]][node] - f1[father[node]][node];
            }
        }
        
        maxFlow += cfpath;
        
        for (int node = t; node != s; node = father[node]) {
            f1[father[node]][node] += cfpath;
            
            // here, instead of modifying the residual capacity
            // (cf[reverse edge] += cfpath)
            // we decrease f1 by cfpath, due to the shift described earlier
            f1[node][father[node]] -= cfpath;
        }
    }
    
    return maxFlow;
}

int main() {
    freopen("maxflow.in", "r", stdin);
    freopen("maxflow.out", "w", stdout);
    
    readAndBuild();
    int F = maxFlowEdmondsKarpWithHacks();
    printf("%d\n", F);
    
    return 0;
}