Cod sursa(job #309942)

Utilizator sandyxpSanduleac Dan sandyxp Data 1 mai 2009 14:50:10
Problema Flux maxim de cost minim Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 2.67 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
#define mp make_pair
#define f first
#define s second

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 {
    inline 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;
}

bool operator<(const pair<int, int> &A, const pair<int, int> &B) {
    return A.f < B.f;
}

int dijkstra(int S, int D)
{
    // HACK. N+M
    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, vector<int>, dist_greater> Q;
    priority_queue<pair<int, int> > Q;

    Q.push(mp(0, S));
    Dist[S] = 0;
    while (!Q.empty()) {
        int x = Q.top().second; 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(mp(Dist[p->nod], 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;
}