Cod sursa(job #282871)

Utilizator sandyxpSanduleac Dan sandyxp Data 18 martie 2009 14:05:32
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 2.44 kb
#include <fstream>
#include <queue>
#include <cstring>
#include <cassert>
using namespace std;

#define NUME "fmcm"
ifstream fi(NUME".in");
ofstream fo(NUME".out");
#define MAXN 351
#define INF 0x3f3f3f3f

int N, M, S, D;
struct list { int nod, cost; list *r; } *L[MAXN];
int F[MAXN][MAXN], C[MAXN][MAXN];
int Dist[MAXN], T[MAXN], tCost;

#define avail(i, j) (C[i][j] - F[i][j])

struct dist_greater {
    bool operator()(const int &A, const int &B) {
        return Dist[A] > Dist[B];
    }
};

int bellman(int S, int D)
{
    int stop = 0, i, j;
    memset(Dist, INF, sizeof(T));
    Dist[S] = 0;

    for (i = 1; i <= N && !stop; ++i) {
        stop = 1;
        for (j = 1; j <= N; ++j)
            for (list *p = L[j]; p; p = p->r)
                if (avail(j, p->nod) > 0 &&
                        Dist[p->nod] > Dist[j] + p->cost) {
                    Dist[p->nod] = Dist[j] + p->cost;
                    stop = 0;
                }
    }
    tCost = Dist[D];
    return stop;
}

int dijkstra(int S, int D)
{
    // HACK
    for (int i = 1; i <= N; ++i)
        for (list *j = L[i]; j; j = j->r)
            if (Dist[i] != INF && Dist[j->nod] != INF)
                j->cost += Dist[i] - Dist[j->nod];
    // Dijkstra
    memset(Dist, INF, sizeof(T));

    priority_queue<int, deque<int>, dist_greater> Q;
    Q.push(S);
    Dist[S] = 0;
    while (!Q.empty()) {
        int x = Q.top(); Q.pop();
        for (list *p = L[x]; p; p = p->r) {
            if (avail(x, p->nod) > 0 && Dist[p->nod] > Dist[x] + p->cost) {
                Dist[p->nod] = Dist[x] + p->cost;
                T[p->nod] = x;
                Q.push(p->nod);
            }
        }
    }
    return Dist[D];
}

void push(int x, int y, int c) {
    list *p = new list;
    *p = (list) { y, c, L[x] };
    L[x] = p;
}

void fluxul(int S, int D)
{
    int f, c, r, dist, i;

    for (f = c = 0; (dist = dijkstra(S, D)) != INF;
            f += r, tCost += dist, c += r*tCost) {
        r = INF;
        for (i = D; i != S; i = T[i])
            r = min(r, avail(T[i], i));
        for (i = D; i != S; i = T[i])
            F[ T[i] ][i] += r, F[i][ T[i] ] -= r;
    }
    fo << c << "\n";
}

void citirea()
{
    int i;
    fi >> N >> M >> S >> D;
    while (M--) {
        int x, y, c, cost;
        fi >> x >> y >> c >> cost;
        push(x, y, cost);
        push(y, x, -cost);
        C[x][y] = c;
    }
}

int main()
{
    citirea();
    assert(bellman(S, D)); // anti-cicluri
    fluxul(S, D);
    return 0;
}