Cod sursa(job #608736)

Utilizator stay_awake77Cangea Catalina stay_awake77 Data 17 august 2011 20:43:15
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.49 kb
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>

#define NMAX 355
#define INF 0x3f3f3f3f
#define pb push_back
#define MIN(a,b) (a<b) ? a : b

using namespace std;

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

int N, M, Sursa, Dest, Nod, Cnt, i, x, y, capacitate, cost, CostMin, FluxCt, Total;
int F[NMAX][NMAX], C[NMAX][NMAX], Cost[NMAX][NMAX], D[NMAX], T[NMAX], H[NMAX], Pos[NMAX];
vector< int > G[NMAX];
vector< int >::iterator Vecin;
queue< int > Q;
bool USED[NMAX];

inline void Swap( int a, int b )
{
    int aux = H[a];
    H[a] = H[b];
    H[b] = aux;

    Pos[ H[a] ] = a;
    Pos[ H[b] ] = b;
}

inline void HeapDown( int NOD )
{
    int Fiu = 2*NOD;

    if( Fiu <= Cnt )
    {
        if( Fiu + 1 <= Cnt && D[ H[Fiu+1] ] < D[ H[Fiu] ] ) ++Fiu;

        if( D[ H[Fiu] ] < D[ H[NOD] ] )
        {
            Swap( Fiu, NOD );
            HeapDown( Fiu );
        }
    }
}

inline void HeapUp( int NOD )
{
    if( NOD > 1 )
    {
        int T = NOD/2;
        if( D[ H[T] ] > D[ H[NOD] ] )
        {
            Swap( T, NOD );
            HeapUp( T );
        }
    }
}

inline void Bellman()
{
    memset( D, INF, sizeof(D) );
    D[Sursa] = 0;

    memset( USED, false, sizeof(USED) );
    Q.push( Sursa );
    USED[Sursa] = true;

    while( !Q.empty() )
    {
        int Nod = Q.front();
        Q.pop();
        USED[Nod] = false;

        for( Vecin = G[Nod].begin(); Vecin != G[Nod].end(); Vecin++ )
            if( F[Nod][*Vecin] < C[Nod][*Vecin] && D[*Vecin] > D[Nod] + Cost[Nod][*Vecin] )
            {
                D[*Vecin] = D[Nod] + Cost[Nod][*Vecin];
                if( !USED[*Vecin] )
                {
                    Q.push( *Vecin );
                    USED[*Vecin] = true;
                }
            }
    }

    Total = D[Dest];
}

inline bool Dijkstra()
{
    for( Nod = 1; Nod <= N; Nod++ )
        if( D[Nod] != INF )
            for( Vecin = G[Nod].begin(); Vecin != G[Nod].end(); Vecin++ )
                if( D[*Vecin] != INF )
                    Cost[Nod][*Vecin] += D[Nod] - D[*Vecin];

    memset( D, INF, sizeof(D) );
    D[Sursa] = 0;

    memset( T, 0, sizeof(T) );
    for( i = 1; i <= N; i++ )
        H[i] = Pos[i] = i;
    Swap( 1, Sursa );
    Cnt = N;

    while( Cnt && D[ H[1] ] != INF )
    {
        int Nod = H[1];
        Swap( 1, Cnt-- );
        HeapDown( 1 );

        for( Vecin = G[Nod].begin(); Vecin != G[Nod].end(); Vecin++ )
            if( F[Nod][*Vecin] < C[Nod][*Vecin] && D[*Vecin] > D[Nod] + Cost[Nod][*Vecin] )
            {
                D[*Vecin] = D[Nod] + Cost[Nod][*Vecin];
                T[*Vecin] = Nod;

                HeapUp( Pos[*Vecin] );
            }
    }

    return ( D[Dest] != INF );
}

int main()
{
    in >> N >> M >> Sursa >> Dest;
    for( ; M--; )
    {
        in >> x >> y >> capacitate >> cost;
        G[x].pb( y );
        G[y].pb( x );

        C[x][y] = capacitate;
        Cost[x][y] = cost;
        Cost[y][x] = -cost;
    }

    Bellman();

    for( CostMin = 0; Dijkstra(); CostMin += FluxCt * Total )
    {
        FluxCt = INF;

        for( Nod = Dest; Nod != Sursa; Nod = T[Nod] )
            FluxCt = MIN( FluxCt, C[ T[Nod] ][Nod] - F[ T[Nod] ][Nod] );

        for( Nod = Dest; Nod != Sursa; Nod = T[Nod] )
            F[ T[Nod] ][Nod] += FluxCt, F[Nod][ T[Nod] ] -= FluxCt;

        Total += D[Dest];
    }

    out << CostMin << '\n';

    return 0;
}