Cod sursa(job #310162)

Utilizator sandyxpSanduleac Dan sandyxp Data 1 mai 2009 21:21:52
Problema Flux maxim de cost minim Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 4.14 kb
#include <fstream>
#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])

#define cmp(i, j) (Dist[i] > Dist[j])
class Heap {
    private:
        int H[MAXN], size, n;
        // cmp:  Dist[A] > Dist[B]    (fiu, tata)

    public:
        int Poz[MAXN];

        void init(int S) {
            int i;
            for (i = 1; i <= n; ++i) {
                H[i] = i;
                Poz[i] = i;
            }
            size = n;
            swap(H[S], H[1]);
            swap(Poz[H[S]], Poz[H[1]]);

            //for (i = n/2; i; --i)
            //    heapdown(i);
        }

        Heap(int n) {
            //H = new int[n+1];
            this->n = n;
            // Poz = new int[n+1];
            size = 0;
        }

        int top() {
            return H[1];
        }

        bool empty() {
            return size == 0;
        }

        int heapup(int x) {
            while (x > 1 && !cmp(H[x], H[x >> 1])) {
                swap(H[x], H[x >> 1]);
                Poz[H[x]] = x;
                Poz[H[x >> 1]] = x >> 1;
                x = x >> 1;
            }
            return x;
        }

        int heapdown(int x) {
            int fiu;
            while( x*2 <= size && !cmp(H[x*2], H[x]) ||
                    x*2+1 <= size && !cmp(H[x*2+1], H[x]) ) {
                fiu = cmp(H[x*2], H[x*2+1]) ? x*2+1 : x*2;
                swap(H[x], H[fiu]);
                Poz[H[x]] = x;
                Poz[H[fiu]] = fiu;
                x = fiu;
            }
            return x;
        }

        void update(int x) {
            x = Poz[x];
            if (heapup(x) == x)
                heapdown(x);
        }

        void remove(int who) {
            int x = Poz[who];
            H[x] = H[size--];
            Poz[H[x]] = x;
            update(x);
        }

        void pop() {
            H[1] = H[size--];
            Poz[H[1]] = 1;
            heapdown(1);
        }
};

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(Dist));
    Dist[S] = 0;

    Heap Q(N);
    Q.init(S); // plecam cu toate la drum
    //Q.push(S);
    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);
                Q.update(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;
}