Cod sursa(job #1464227)

Utilizator petru.cehanCehan Petru petru.cehan Data 22 iulie 2015 17:30:47
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 4.06 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>

using namespace std;

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

const int Nmax = 350 + 1 ;
const int Mmax = 12500 + 1 ;
const int INF = 10000 + 1 ;

vector < int > G[Nmax] ;

int Capacity[Nmax][Nmax] ;
int Flow[Nmax][Nmax] ;
int Cost[Nmax][Nmax] ;

queue <int> Q ;
int dist[Nmax] ;
bool in_queue[Nmax] ;

priority_queue< pair < int , int > , vector < pair < int , int > > , greater < pair < int , int > > > MinHeap ;

int tata[Nmax] ;

int N , M ;

void addEdge ( int x , int y , int cap , int c )
{
    G[x].push_back(y) ;
    G[y].push_back(x) ;

    Capacity[x][y] = cap ;
    Capacity[y][x] = 0 ;

    Cost[x][y] = c ;
    Cost[y][x] = -c ;
}

bool Bellman_Ford(int S, int T)
{
    for ( int i = 1 ; i <= N ; ++ i )
    {
        dist[i] = INF ;
        in_queue[i] = false ;
        tata[i] = 0 ;
    }

    Q.push(S) ;
    in_queue[S] = false;
    dist[S] = 0 ;
    tata[S] = S ;

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

        for ( vector < int > :: iterator son = G [nod].begin () ; son != G [nod].end() ; son ++ )
        {
            if ( ( Capacity[nod][*son] > Flow[nod][*son]) && dist[*son] > dist[nod] + Cost[nod][*son] )
            {
                dist[*son] = dist[nod] + Cost[nod][*son] ;
                tata[*son] = nod ;

                if ( !in_queue[*son] )
                {
                    in_queue[*son] = true ;
                    Q.push(*son) ;
                }
            }
        }
    }

    return ( dist[T] != INF ) ;
}

void updateCosts()
{
    for ( int i = 1 ; i <= N ; ++ i )
    {
        if ( dist[i] != INF )
        {
            for ( vector < int > :: iterator son = G [i].begin () ; son != G [i].end() ; son ++ )
            {
                if ( dist[*son] != INF )
                    Cost[i][*son] += dist[i] - dist[*son];
            }
        }
    }
}

int Dijkstra ( int S , int T )
{
    updateCosts() ; // facem costurile pozitive

    for ( int i = 1 ; i <= N ; ++ i )
    {
        dist[i] = INF ;
        in_queue[i] = false ;
        tata[i] = 0 ;
    }

    MinHeap.push({0, S}) ;
    dist[S] = 0 ;
    tata[S] = S ;

    while ( !MinHeap.empty() )
    {
        int nod = MinHeap.top().second ;
        int auxD = MinHeap.top().first ;
        MinHeap.pop() ;

        if ( auxD != dist[nod] )
            continue ;

        for ( vector < int > :: iterator son = G [nod].begin () ; son != G [nod].end() ; son ++ )
        {
            if (( Capacity[nod][*son] > Flow[nod][*son]) && dist[*son] > dist[nod] + Cost[nod][*son])
            {
                dist[*son] = dist[nod] + Cost[nod][*son];
                tata[*son] = nod;

                MinHeap.push({dist[*son], *son});
            }
        }
    }

    return ( dist[T] != INF ) ;
}

pair < int , long long > minCostMaxFlow ( int S, int T )
{
    int flow = 0 ;
    long long costFlow = 0 ;
    long long totalDist = 0 ;

    Bellman_Ford ( S , T ) ;
    totalDist = dist[T] ;

    while ( Dijkstra( S , T ) )
    {
        int fmin = INF ;
        int nod = T ;

        while (nod != S)
        {
            fmin = min ( fmin , Capacity[ tata[nod] ][nod] - Flow[ tata[nod] ][nod] ) ;
            nod = tata[nod] ;
        }

        nod = T ;

        while ( nod != S )
        {
            Flow[ tata[nod] ][nod] += fmin ;
            Flow[nod][ tata[nod] ] -= fmin ;
            nod = tata[nod] ;
        }

        flow += fmin ;
        totalDist += dist[T] ;
        costFlow += (long long)fmin * totalDist ;
    }

    return make_pair ( flow , costFlow ) ;
}

int main()
{
    int S , T ;

    fin >> N >> M >> S >> T ;

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

        addEdge ( x , y , cap , cost ) ;
    }

    fout << minCostMaxFlow(S, T).second << "\n" ;

    return 0;
}