Cod sursa(job #963426)

Utilizator matei_cChristescu Matei matei_c Data 17 iunie 2013 14:16:04
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.88 kb
#include<fstream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std ;

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

#define maxn 351
#define inf 10000

int N, M, sursa, destinatie ;
vector<int> graf[maxn] ;

queue<int> coada ;
priority_queue< pair< int, int > > heap ;

int cap[maxn][maxn], cost[maxn][maxn] ;
int fact[maxn], dist[maxn], flux[maxn], tata[maxn] ;

void citire()
{
    fin >> N >> M >> sursa >> destinatie ;

    for(int i = 0; i < M; ++i )
    {
        int x, y, capacitate, c ;

        fin >> x >> y >> capacitate >> c ;

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

        cap[x][y] = capacitate ;

        cost[x][y] = c ;
        cost[y][x] = -c ;

    }
}

bool dijkstra()
{
    for(int i = 1; i <= N; ++i )
        dist[i] = inf ;

    dist[sursa] = 0 ;
    flux[sursa] = 0 ;
    heap.push( make_pair( 0, sursa ) ) ;

    while( heap.empty() == false )
    {
        int nod = heap.top().second ;
        int dact = -heap.top().first ;
        heap.pop() ;

        if( dist[nod] < dact )
            continue ;

        for(size_t i = 0; i < graf[nod].size(); ++i )
        {
            int vecin = graf[nod][i] ;

            if( cap[nod][vecin] )
            {
                dact = fact[nod] + cost[nod][vecin] - fact[vecin] ;

                if( dist[vecin] <= dist[nod] + dact )
                    continue ;

                dist[vecin] = dist[nod] + dact ;
                flux[vecin] = flux[nod] + cost[nod][vecin] ;
                tata[vecin] = nod ;

                heap.push( make_pair( -dist[vecin], vecin ) ) ;
            }
        }
    }

    memcpy( fact, flux, sizeof(flux) ) ;

    return ( dist[destinatie] != inf ) ;

}

int main ()
{
    citire() ;

    memset( fact, inf, sizeof(fact) ) ;
    fact[sursa] = 0 ;
    coada.push(sursa) ;

    while( coada.empty() == false )
    {
        int nod = coada.front() ;
        coada.pop() ;

        for(size_t i = 0; i < graf[nod].size(); ++i )
        {
            int vecin = graf[nod][i] ;

            if( cap[nod][vecin] && fact[vecin] > fact[nod] + cost[nod][vecin] )
            {
                fact[vecin] = fact[nod] + cost[nod][vecin] ;
                coada.push(vecin) ;
            }
        }
    }

    int sol = 0 ;

    while( dijkstra() == true )
    {
        int fluxmin = inf ;

        int nod = destinatie ;
        while( nod != sursa )
        {
            fluxmin = min( fluxmin, cap[ tata[nod] ][nod] ) ;
            nod = tata[nod] ;
        }

        nod = destinatie ;
        while( nod != sursa )
        {
            cap[ tata[nod] ][nod] -= fluxmin ;
            cap[nod][ tata[nod] ] += fluxmin ;
            nod = tata[nod] ;
        }

        sol += fluxmin * flux[destinatie] ;
    }

    fout << sol ;

    return 0 ;
}