Cod sursa(job #1808311)

Utilizator monicalegendaLegenda Monica monicalegenda Data 17 noiembrie 2016 16:42:51
Problema Flux maxim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.12 kb
#include <fstream>
#include <vector>
#include <queue>
#include <limits.h>
#include <string.h>
#include <iostream>
#define NMAX 1001

using namespace std;

typedef vector< vector<int> > Graph;


int F[NMAX][NMAX]; // fluxul pe muchia i -> j
int C[NMAX][NMAX]; // capacitatea muchiei i -> j
bool visited[NMAX]; // nodul i vizitat in bfs sau nu
int previous[NMAX]; // precedentul lui i in bfs

/* intoarce true daca ajunge la destinatie
   definitia mai jos (altfel aveam niste erori de la variabilele globale) */
bool bfs(Graph &graph, int n);

int main()
{
    ifstream fin("maxflow.in");
    ofstream fout("maxflow.out");

    int n, m;
    int fmin; // minimul pe o cale
    int total_flow;
    int prevn; // un precedent al lui n

    fin >> n >> m;
    Graph graph(n + 1);

    int v1, v2, capacity;
    for (int i = 1; i <= m; i++) {
        fin >> v1 >> v2 >> capacity;
        graph[v1].push_back(v2); // muchie directa, cu capacitatea data
        graph[v2].push_back(v1); // muchie inversa, capacitate 0
        C[v1][v2] += capacity; // poti avea mai multe muchii intre doua noduri
    }

    total_flow = 0;
    do {
        // daca nu mai exista drum de la 1 la n, break
        if(!bfs(graph, n)) {
            break;
        }

        // incercam sa folosim drumul gasit adineauri pentru mai multi predecesori
        // ai lui n (ii putem gasi pt ca am pus in graf si muchiile inverse)
        for (unsigned int i = 0; i < graph[n].size(); i++) {
            prevn = graph[n][i];

            // daca muchia este deja saturata sau prevn nu apartine drumului
            // gasit, o ignoram
            if (F[prevn][n] == C[prevn][n] || !visited[prevn]) {
                continue;
            }

            // gasim reziduul maxim ramas pe drum
            previous[n] = prevn;
            fmin = INT_MAX;
            for (int j = n; j != 1; j = previous[j]) {
                fmin = min(fmin, C[previous[j]][j] - F[previous[j]][j]);
            }
            if (fmin == 0) {
                continue;
            }

            // actualizam flow-urile
            for (int j = n; j != 1; j = previous[j]) {
                F[previous[j]][j] += fmin;
                F[j][previous[j]] -= fmin;
            }
            total_flow += fmin;
        }
    } while (true);

    fout << total_flow;

    return 0;
}


bool bfs(Graph &graph, int n) {
    memset(visited, false, NMAX * sizeof(bool));
    queue<int> bfs_q;

    bfs_q.push(1);
    visited[1] = true;

    int node, next;
    while(!bfs_q.empty()) {
        node = bfs_q.front();
        bfs_q.pop();

        // gasim intr-un bfs drumuri spre toti predecesorii lui n => nu ne
        // oprim cand dam de n
        if (node == n) {
            continue;
        }

        for (unsigned int i = 0; i < graph[node].size(); i++) {
            next = graph[node][i];
            if (C[node][next] > F[node][next] && !visited[next]) {
                visited[next] = true;
                bfs_q.push(next);
                previous[next] = node;
            }
        }
    }
    return visited[n];
}