Cod sursa(job #1211548)

Utilizator mariusn01Marius Nicoli mariusn01 Data 22 iulie 2014 20:16:27
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.71 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#define DIM 355
#define INF 100000000
using namespace std;

ifstream fin("fmcm.in");
ofstream fout("fmcm.out");

vector<int> L[DIM];
int C[DIM][DIM], F[DIM][DIM], Z[DIM][DIM];
int D[DIM], V[DIM], E[DIM], H[DIM], P[DIM], T[DIM], R[DIM];
queue<int> Q;

int n, m, c, z, i, j, cost, inHeap, x, y, s, d, dH, p, minim;

void swap(int &a, int &b) {
    int aux = a;
    a = b;
    b = aux;
}

int dijkstra() {
    int ok = 0;

    memset(T, 0, sizeof(T));
    for (int i=1;i<=n;i++)
        E[i] = INF;
    E[s] = 0;

    R[s] = 0;
    H[1] = s;
    dH = 1;
    P[s] = 1;
    while (dH) {
        x = H[1];
        H[1] = H[dH--];
        P[H[1]] = 1;
        p = 1;
        c = 2;
        while (c <= dH) {
            if (c+1 <= dH && E[ H[c+1] ] < E[ H[c] ])
                c++;
            if ( E[ H[p] ] > E[ H[c] ] ) {
                swap(H[p], H[c]);
                P[ H[p] ] = p;
                P[ H[c] ] = c;
                p = c;
                c = 2*p;
            } else
                break;
        }

        for (int i=0;i<L[x].size();i++) {
            y = L[x][i];
            if (E[ y ] > E[ x ] + Z[x][y] + D[x] - D[y]   && C[x][y] > F[x][y]) {
                T[y] = x;
                if (y == d)
                    ok = 1;
                if (E[y] == INF)
                    inHeap = 0;
                else
                    inHeap = 1;
                E[ y ] = E[ x ] + Z[x][y] + D[x] - D[y];
                R[y] = R[x] + Z[x][y];
                if (inHeap == 0) {
                    dH++;
                    H[dH] = y;
                    P[ H[dH] ] = dH;
                    c = dH;
                } else
                    c = P[ y ];
                while (p > 0) {
                    if (E[ H[p] ] > E[ H[c] ]) {
                        swap(H[p], H[c]);
                        P[ H[p] ] = p;
                        P[ H[c] ] = c;
                        c = p;
                        p = p/2;
                    } else
                        break;
                }
            }
        }
    }
    memcpy(D, E, sizeof(D));
    return ok;
}

int main() {
    fin>>n>>m>>s>>d;
    for (i=1;i<=m;i++) {
        fin>>x>>y>>c>>z;
        L[x].push_back(y);
        L[y].push_back(x);
        C[x][y] = c;
        Z[x][y] = z;
        Z[y][x] = -z;
    }

    // calculez, cu bellman ford distanta minima se la s la toate
    // nodurile, in vectorul D
    Q.push(s);
    V[s] = 1;
    for (i=1;i<=n;i++)
        D[i] = INF;
    D[s] = 0;

    while (!Q.empty()) {
        x = Q.front();
        Q.pop();
        V[x] = 0;

        for (int i=0;i<L[x].size();i++)
            if ( C[x][L[x][i]]>F[x][L[x][i]] && D[ L[x][i] ] > D[x] + Z[x][ L[x][i] ]) {
                D[ L[x][i] ] = D[x] + Z[x][ L[x][i] ];
                if (V[L[x][i]] == 0) {
                    V[L[x][i]] = 1;
                    Q.push(L[x][i]);
                }
            }
    }

/*
    for (i=1;i<=n;i++)
        for (j=0;j<L[i].size();j++) {
            Z[i][ L[i][j] ] += (D[i] - D[ L[i][j] ]);
        }
*/
    while (dijkstra()) {
        minim = INF;
        y = d;
        do {
            x = T[y];
            minim = min(minim, C[x][y] - F[x][y]);
            y = x;
        } while (y!=s);

//        cout<<minim<<"\n";

        if (minim) {
            y = d;
            do {
                x = T[y];
                F[x][y] += minim;
                F[y][x] -= minim;
                y = x;
            } while (y!=s);
            cost += (R[d]*minim);
        }

    }

    fout<<cost<<"\n";

    return 0;
}