Cod sursa(job #698519)

Utilizator tamas_iuliaTamas Iulia tamas_iulia Data 29 februarie 2012 14:36:20
Problema Flux maxim de cost minim Scor 20
Compilator cpp Status done
Runda Arhiva educationala Marime 3.34 kb
#include <stdio.h>
#include <string.h>
#include <vector>
#include <queue>
#define Nmax 355
#define INF 2147000000
#define pb push_back
using namespace std;

vector< int > v[Nmax];
queue< int > Q;
int F[Nmax][Nmax],C[Nmax][Nmax],Cost[Nmax][Nmax];
int dist[Nmax],h[Nmax],poz[Nmax],prev[Nmax],inq[Nmax];
int N,M,S,D,Sum,ok,cost_flow,dh;

inline void read()
{
    int i,x,y,cap,cost;
    freopen("fmcm.in","r",stdin);
    freopen("fmcm.out","w",stdout);
    scanf("%d%d%d%d",&N,&M,&S,&D);

    for(i=1; i<=M; ++i)
    {
        scanf("%d%d%d%d",&x,&y,&cap,&cost);
        v[x].pb(y);
        v[y].pb(x);
        C[x][y] = cap;
        Cost[x][y] = cost;
        Cost[y][x] = -cost;
    }
}

inline void BF()
{
    vector< int >:: iterator it;
    int f;

    memset( prev, 0, sizeof(prev) );
    while( ! Q.empty() ) Q.pop();
    Q.push( S );

    for(int i = 1; i<=N; ++i) dist[i] = INF;
    dist[S] = 0;

    while( ! Q.empty() )
    {
        f = Q.front(); Q.pop();
        inq[ f ] = 0;

        if( f == D ) continue;

        for( it=v[f].begin(); it!=v[f].end(); ++it)
            if( C[f][*it] > F[f][*it] && dist[*it] > dist[f] + Cost[f][*it] )
            {
                dist[*it] = dist[f] + Cost[f][*it];

                if( ! inq[ *it] )
                {
                    inq[ *it ] = 1;
                    Q.push( *it );
                }
            }
    }

    Sum = dist[ D ];
}

inline void swap( int i, int j)
{
    int aux;
    aux=h[i], h[i] = h[j], h[j]=aux;
    poz[h[i]] = i;
    poz[h[j]] = j;
}

inline void Up( int k )
{
    while ( k/2 && dist[ h[k] ] < dist[ h[k/2] ] )
    {
        swap( k, k/2 );
        k/=2;
    }
}

inline void Down( int k )
{
    int mn=0;
    while( mn != k )
    {
        mn = k;
        if( k*2 <= dh && dist[ h[2*k] ] < dist[ h[mn] ] ) mn = 2*k;
        if( k*2+1 <= dh && dist[ h[2*k+1] ] < dist[ h[mn] ] ) mn = 2*k+1;

        swap( k, mn );
    }
}

inline void Flux()
{
    vector< int >:: iterator it;
    int i,pmin,fmin,wh;

    for( i=1; i<=N; ++i)
        if( dist[ i ] != INF )
            for( it=v[i].begin(); it!=v[i].end(); ++it)
                if( dist[*it] != INF )
                    Cost[ i ][ *it ] += dist[i] - dist[*it];

    for( i=1; i<=N; ++i ) dist[i] = INF, h[i]=poz[i]=i;
    dist[ S ] = 0;
    Up( S );
    dh = N;

    while( dh )
    {
        pmin = h[1];
        swap( 1, dh );
        dh--;
        Down( 1 );

        for( it=v[pmin].begin(); it!=v[pmin].end(); ++it )
            if( C[pmin][*it] > F[pmin][*it] && dist[ *it ] > dist[ pmin ] + Cost[pmin][*it] )
            {
                dist[ *it ] = dist[ pmin ] + Cost[pmin][*it];
                prev[ *it ] = pmin;
                Up( poz[ *it ] );
            }
    }

    if( dist[ D ] == INF ) return;
    ok = 1;

    fmin = INF;
    for( wh = D; wh != S; wh = prev[ wh ] )
        fmin = min( fmin, C[prev[wh]][wh] - F[prev[wh]][wh] );

    for( wh = D; wh != S; wh = prev[ wh ] )
    {
        F[prev[wh]][wh] += fmin;
        F[wh][prev[wh]] -= fmin;
    }

    Sum += dist[ D ];
    cost_flow += Sum * fmin;
}

int main()
{
    read();
    BF();

    do
    {
        ok = 0;
        Flux();
    } while( ok );

    printf("%d\n",cost_flow);
    fclose(stdin); fclose(stdout);
    return 0;
}