Cod sursa(job #244829)

Utilizator toni2007Pripoae Teodor Anton toni2007 Data 16 ianuarie 2009 01:48:21
Problema Flux maxim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.86 kb
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <bitset>
#include <queue>

using namespace std;

#define FIN "maxflow.in"
#define FOUT "maxflow.out"
#define NMAX 1024
#define oo 1000000

int N, M;
int C[NMAX][NMAX];                      // capacitatea muchiei intre i si j
vector<int> Cine[NMAX];                 // lista de adiacenta
bitset<NMAX> viz;
int SOURCE, DEST;                       // sursa si destinatia
int Tata[NMAX];                         // vector pentru reconstituirea drumului
int F[NMAX][NMAX];                      // matricea cu fluxul intre i si j
int flowMax;                            // fluxul maxim

inline int min(int a,int b){
    if (a < b)
        return a;
    return b;
}
bool BF(){
    queue<int> Q;
    int i, now, nod;

    Q.push(SOURCE);
    viz.reset();
    viz[SOURCE] = 1;

    while (!Q.empty()){         // cat timp coada nu e vida
        nod = Q.front();
        if (nod == DEST) break;   // daca am ajuns la destinatie ma opresc
        for (i = 0; i < Cine[nod].size(); ++i){       // parcurg vecinii
            now = Cine[nod][i];

            if (F[nod][now] == C[nod][now] || viz[now])
                continue; // daca fluxul e egal cu capacitatea, nu mai pot adauga
                          // iar daca a fost vizitat inainte nu mai am de ce sa ii modific
            viz[now] = 1; // il marchez ca vizitat
            Q.push(now);  // il adaug in coada
            Tata[now] = nod;  // tatal lui devine Q.front
        }
        Q.pop();
    }

    return viz[DEST];
}
void flux(){
    int i, now, fMin;
    SOURCE = 1; DEST = N;
    for (; BF(); ){         // atata timp cat pot ajunge in destinatie
        for (i = 0; i < Cine[DEST].size(); ++i){ // parcurg vecinii lui N
            now = Cine[DEST][i];
            if (F[now][DEST] == C[now][DEST] || !viz[now])
                continue; // daca fluxul e egal cu capacitatea sau nu a fost vizitat

            Tata[DEST] = now;
            fMin = oo; // fac fluxul minim pe drum infinit

            for (now = DEST; now != 1; now = Tata[now]) // parcurg un drum care nu e utilizat la maxim
                fMin = min(fMin, C[Tata[now]][now] - F[Tata[now]][now]);

            if (fMin == 0)
                continue; // daca mai pot adauga flux continui

            for (now = DEST; now != 1; now = Tata[now]) { // parcurg drumul
                F[Tata[now]][now] += fMin; // cresc fluxul pe muchia directa
                F[now][Tata[now]] -= fMin; // scad fluxul pe muchia inversa
            }
            flowMax += fMin;   // adaug la fluxul maxim fMin
        }
    }
}
int main(){
    int i, a, b, c;

    freopen(FIN, "r", stdin);
    freopen(FOUT, "w", stdout);

    scanf("%d %d", &N, &M);

    for (i = 0; i < M; ++i){
        scanf("%d %d %d", &a, &b, &c);
        C[a][b] += c;
        Cine[a].push_back(b);
        Cine[b].push_back(a);
    }

    flux();

    printf("%d\n", flowMax);

}