Cod sursa(job #243584)

Utilizator Mishu91Andrei Misarca Mishu91 Data 13 ianuarie 2009 17:30:09
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.08 kb
#include <cstdio>
#include <vector>

using namespace std;

#define MAX_N 355
#define INF 0x3f3f3f

#define foreach(V) for(typeof (V).begin() it = (V).begin(); it != (V).end(); ++it)

vector <int> G[MAX_N];
int N, M, S, D;
int Cap[MAX_N][MAX_N], Cost[MAX_N][MAX_N], F[MAX_N][MAX_N];
int Dist[MAX_N], H[MAX_N], From[MAX_N], P[MAX_N];
int Sum, L;
bool Drum = 1;

void push(int x)
{
	int aux;

	while (x/2>1 && Dist[H[x]]<Dist[H[x/2]])
	{
		aux = H[x], H[x] = H[x/2], H[x/2] = aux;

		P[H[x]] = x;
		P[H[x/2]] = x/2;

		x /= 2;
	}
}

void pop(int x)
{
	int y = 0, aux;

	while (x != y)
	{
		y = x;
		if (y*2<=L && Dist[H[x]]>Dist[H[y*2]]) x = y*2;
		if (y*2+1 <= L && Dist[H[x]]>Dist[H[y*2+1]]) x = y*2+1;

		aux = H[x], H[x] = H[y], H[y] = aux;
		P[H[x]] = x;
		P[H[y]] = y;
	}
}

void BelmanFord()
{
    bool ok = 0;
    for(int i = 1; i <= N; ++i)
        Dist[i] = INF;

    Dist[S] = 0;

    for(int i = 1; i <= N && !ok; ++i)
    {
        ok = 1;

        for(int j = 1; j <= N; ++j)
            foreach(G[j])
                if(Cap[j][*it] - F[j][*it] > 0 && Dist[j] + Cost[j][*it] < Dist[*it])
                {
                    ok = 0;
                    Dist[*it] = Dist[j] + Cost[j][*it];
                }
    }
    Sum = Dist[D];
}

void citire()
{
    scanf("%d %d %d %d",&N, &M, &S, &D);

    for(int i = 1; i <= M; ++i)
    {
        int x, y, cap, cost;

        scanf("%d %d %d %d",&x, &y, &cap, &cost);

        G[x].push_back(y);
        G[y].push_back(x);

        Cap[x][y] = cap;
        Cost[x][y] = cost;
        Cost[y][x] = -cost;
    }
}

long long Dijkstra()
{
    for(int i = 1; i <= N; ++i)
        foreach(G[i])
            if(Dist[i] != INF && Dist[*it] != INF)
                Cost[i][*it] += (Dist[i] - Dist[*it]);

    for(int i = 1; i <= N; ++i)
    {
        Dist[i] = INF;
        H[i] = i;
        P[i] = i;
        From[i] = -1;
    }
    Dist[S] = 0;
    H[1] = S, H[S] = 1;
    P[1] = S, P[S] = 1;
    L = N;

    while(L > 1 && Dist[H[1]] != INF)
    {
        foreach(G[H[1]])
        {
            int v = *it;

            if(Cap[H[1]][v] - F[H[1]][v] > 0 && Dist[H[1]] + Cost[H[1]][v] < Dist[v])
            {
                Dist[v] = Dist[H[1]] + Cost[H[1]][v];
                From[v] = H[1];
                push(P[v]);
            }
        }

        H[1] = H[L--];
        P[H[1]] = 1;
        if(L > 1) pop(1);
    }
    if(Dist[D] != INF)
    {
        int V = INF;
        Drum = 1;

        for(int i = D; i != S; i = From[i])
            V = min(V, Cap[From[i]][i] - F[From[i]][i]);

        for(int i = D; i != S; i = From[i])
        {
            F[From[i]][i] += V;
            F[i][From[i]] -= V;
        }

        Sum += Dist[D];
        return V * Sum;
    }
    return 0;
}

int main()
{
    freopen("fmcm.in","rt",stdin);
    freopen("fmcm.out","wt",stdout);

    citire();
    BelmanFord();

    long long Rez = 0;

    while(Drum)
    {
        Drum = 0;
        Rez += Dijkstra();
    }

    printf("%lld\n",Rez);
}