Cod sursa(job #1555416)

Utilizator bciobanuBogdan Ciobanu bciobanu Data 22 decembrie 2015 19:18:41
Problema Flux maxim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.84 kb
// Edmonds - Karp
// O (N * M * M)
#include <fstream>
#include <algorithm>

using namespace std;

const int kMaxN = 1000;
const int kMaxM = 5000;
const int kInf = 2000000000;
const int NIL = -1;

struct Edge {
    int v, next;
    int cap;
};

Edge l[2 * kMaxM];      // buffer de liste alocate static, pozitiile impare corespund muchiilor din reteaua reziduala
int adj[kMaxN];         // capete de liste de adiacenta

int Q[kMaxN];           // coada BFS
int qStart, qEnd;

int father[kMaxN];      // vector de tati, pentru drumul de ameliorare
int edgePointer[kMaxN]; // pointer catre muchia orientata tata -> fiu   
int N;

void addEdge(const int &u, const int &v, const int &cap, const int &pos) {
    l[pos].v = v;
    l[pos].cap = cap;
    l[pos].next = adj[u];
    adj[u] = pos;
}

int BFS(const int &source, const int &sync) {
    int u, v;

    for (int i = 0; i < N; i++) {
        father[i] = NIL;
    }

    // cauta drumul de ameliorare
    father[source] = source;
    qStart = 0;
    qEnd = 1;
    Q[0] = source;
    do {
        u = Q[qStart++];
        for (int i = adj[u]; i != NIL; i = l[i].next) {
            v = l[i].v;
            if ((father[v] == NIL) && (l[i].cap != 0)) {
                father[v] = u;
                edgePointer[v] = i;
                Q[qEnd++] = v;
            }
        }
    } while ((qStart != qEnd) && (father[sync] == NIL));

    int flow = 0;

    // pornind de la destinatie
    for (int i = adj[sync]; i != NIL; i = l[i].next) {
        v = l[i].v;

        if ((father[v] != NIL) && (l[i ^ 1].cap)) { // muchia e orientata
            father[sync] = v;                       // v -> destinatie = i ^ 1
            edgePointer[sync] = i ^ 1;

            // vor fi saturate toate muchiile de capacitate minim

            int minFlow = kInf;

            u = sync;

            do {
                minFlow = min(minFlow, l[edgePointer[u]].cap);
                u = father[u];
            } while (u != source);

            u = sync;

            do {
                l[edgePointer[u]].cap -= minFlow;      // scade din capacitatea muchiei
                l[edgePointer[u] ^ 1].cap += minFlow;  // adauga in reteaua reziduala
                u = father[u];
            } while (u != source);

            flow += minFlow;
        }
    }
    return flow;
}

int main(void) {
    ifstream in("maxflow.in");
    ofstream out("maxflow.out");
    int M;

    in >> N >> M;
    for (int i = 0; i < N; i++) {
        adj[i] = NIL;
    }
    for (int i = 0; i < M; i++) {
        int u, v, cap;
        in >> u >> v >> cap;
        addEdge(u - 1, v - 1, cap, 2 * i);      // retea de transport
        addEdge(v - 1, u - 1, 0, 2 * i + 1);    // retea reziduala
    }
    in.close();

    int flow = 0, augment;
    do {
        augment = BFS(0, N - 1);
        flow += augment;
    } while (augment);

    out << flow << '\n';
    out.close();
	return 0;
}