Cod sursa(job #984724)

Utilizator AlexandruValeanuAlexandru Valeanu AlexandruValeanu Data 15 august 2013 11:19:53
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.54 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <cstring>
#include <cassert>

using namespace std;

#define Nmax 355
#define INF 0x3f3f3f3f

class cmp
{
    public:

        bool operator()( const pair<int,int> &a, const pair<int,int> &b )
        {
            return a.second > b.second;
        }
};

int N, M, S, D;
int flow, flow_cost;

vector <int> graph[Nmax];

int C[Nmax][Nmax];
int Cst[Nmax][Nmax];

int dist[Nmax];
int real_dist[Nmax];
int old_dist[Nmax];
int tata[Nmax];
bool in_queue[Nmax];

queue <int> Q;
priority_queue < pair<int,int>, vector <pair<int,int>>, cmp > heap;

inline bool Dijkstra( int source, int destination )
{
    memset( dist, INF, sizeof( dist ) );

    dist[source] = 0;
    real_dist[source] = 0;

    heap.push( make_pair( source, 0 ) );

    while( !heap.empty() )
    {
        int cst = heap.top().second;
        int nod = heap.top().first;
        heap.pop();

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

        for ( unsigned i = 0; i < graph[nod].size(); ++i )
        {
            int son = graph[nod][i];

            if ( C[nod][son] )
            {
                int new_d = dist[nod] + Cst[nod][son] + old_dist[nod] - old_dist[son];

                if ( new_d < dist[son] )
                {
                    dist[son] = new_d;
                    real_dist[son] = real_dist[nod] + Cst[nod][son];
                    tata[son] = nod;

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

    memcpy( old_dist, real_dist, sizeof( old_dist ) );

    if ( dist[destination] == INF )
            return false;

    int minim = INF, current_cost = 0, nod;

    for ( nod = destination; nod != source; nod = tata[nod] )
            minim = min( minim, C[ tata[nod] ][nod] ),
            current_cost += C[ tata[nod] ][nod];

    flow += minim;
    flow_cost += minim * real_dist[destination];

    for ( nod = destination; nod != source; nod = tata[nod] )
    {
        C[nod][ tata[nod] ] += minim;
        C[ tata[nod] ][nod] -= minim;
    }

    return true;
}

inline bool BellmanFord( int source, int destination )
{
    memset( old_dist, INF, sizeof( old_dist ) );

    old_dist[source] = 0;

    Q.push( source );
    in_queue[source] = 1;

    while( !Q.empty() )
    {
        int nod = Q.front();
        Q.pop();

        for ( unsigned i = 0; i < graph[nod].size(); ++i )
        {
            int son = graph[nod][i];

            if ( C[nod][son] )
            {
                if ( old_dist[son] + Cst[nod][son] >= old_dist[son] )
                        continue;

                old_dist[son] = old_dist[nod] + Cst[nod][son];

                if ( in_queue[son] )
                        continue;

                in_queue[son] = 1;
                Q.push( son );
            }
        }
    }

    if ( old_dist[destination] == INF )
            return false;
    else
            return true;
}

void read()
{
    ifstream f("fmcm.in");

    f >> N >> M >> S >> D;

    for ( int x, y; M; M-- )
    {
        f >> x >> y;
        f >> C[x][y] >> Cst[x][y];

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

        Cst[y][x] = -Cst[x][y];
    }

}

void print()
{
    ofstream g("fmcm.out");

    g << flow_cost << "\n";

    g.close();
}

int main()
{
    read();
    BellmanFord( S, D );
    for ( ; Dijkstra( S, D ); );
    print();

    return 0;
}