Cod sursa(job #601276)

Utilizator a_h1926Heidelbacher Andrei a_h1926 Data 5 iulie 2011 20:01:36
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.92 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>

#define Infinit 2000000000
#define NMax 400

using namespace std;

vector <int> G[NMax];
int N, Start, Dest, Cap[NMax][NMax], Flow[NMax][NMax], Cost[NMax][NMax], DistD;
int D[NMax], H[NMax], NH, P[NMax], Father[NMax];

void Read ()
{
    ifstream fin ("fmcm.in");
    int M;
    fin >> N >> M >> Start >> Dest;
    for (; M>0; --M)
    {
        int x, y, z, c;
        fin >> x >> y >> c >> z;
        G[x].push_back (y);
        G[y].push_back (x);
        Cap[x][y]=c;
        Cost[x][y]=z;
        Cost[y][x]=-z;
    }
    fin.close ();
}

inline int Min (int a, int b)
{
    if (a<b)
    {
        return a;
    }
    return b;
}

void BellmanFord ()
{
    queue <int> Queue;
    bool InQueue[NMax];
    for (int i=1; i<=N; ++i)
    {
        D[i]=Infinit;
        InQueue[i]=false;
    }
    D[Start]=0;
    Queue.push (Start);
    InQueue[Start]=true;
    while (!Queue.empty ())
    {
        int X=Queue.front ();
        Queue.pop ();
        InQueue[X]=false;
        for (int i=0; i<G[X].size (); ++i)
        {
            int V=G[X][i];
            if (D[X]+Cost[X][V]<D[V] and Cap[X][V]-Flow[X][V]>0)
            {
                D[V]=D[X]+Cost[X][V];
                if (!InQueue[V])
                {
                    Queue.push (V);
                    InQueue[V]=true;
                }
            }
        }
    }
}

inline void Swap (int X, int Y)
{
    int Aux;
    Aux=P[H[X]];
    P[H[X]]=P[H[Y]];
    P[H[Y]]=Aux;
    Aux=H[X];
    H[X]=H[Y];
    H[Y]=Aux;
}

void Percolate (int X)
{
    int F=X/2;
    while (F>0)
    {
        if (D[H[X]]<D[H[F]])
        {
            Swap (X, F);
            X=F;
            F=X/2;
        }
        else
        {
            return ;
        }
    }
}

void Sift (int X)
{
    int S=2*X;
    while (S<=NH)
    {
        if (S+1<=NH and D[H[S+1]]<D[H[S]])
        {
            S++;
        }
        if (D[H[X]]>D[H[S]])
        {
            Swap (X, S);
            X=S;
            S=2*X;
        }
        else
        {
            return;
        }
    }
}

void Delete (int X)
{
    Swap (X, NH);
    NH--;
    Sift (X);
}

void Init ()
{
    for (int i=1; i<=N; ++i)
    {
        for (int j=0; j<G[i].size (); ++j)
        {
            int V=G[i][j];
            if (D[i]!=Infinit and D[V]!=Infinit)
            {
                Cost[i][V]+=(D[i]-D[V]);
            }
        }
    }
    for (int i=1; i<=N; ++i)
    {
        D[i]=Infinit;
        H[i]=i;
        P[i]=i;
        Father[i]=0;
    }
    NH=N;
    D[Start]=0;
    Swap (1, Start);
}

bool Dijkstra ()
{
    int X, C, V;
    Init ();
    while (NH>1 and D[H[1]]!=Infinit)
    {
        X=H[1];
        Delete (1);
        for (int i=0; i<G[X].size (); ++i)
        {
            V=G[X][i];
            C=Cost[X][V];
            if (D[X]+C<D[V] and Cap[X][V]-Flow[X][V]>0)
            {
                D[V]=D[X]+C;
                Father[V]=X;
                Percolate (P[V]);
            }
        }
    }
    if (D[Dest]<Infinit)
    {
        return true;
    }
    return false;
}

long long CalculateFlow ()
{
    long long CostMaxFlow=0;
    int F;
    BellmanFord ();
    DistD=D[Dest];
    while (Dijkstra ())
    {
        F=Infinit;
        for (int X=Dest; X!=Start; X=Father[X])
        {
            F=Min (F, Cap[Father[X]][X]-Flow[Father[X]][X]);
        }
        for (int X=Dest; X!=Start; X=Father[X])
        {
            Flow[Father[X]][X]+=F;
            Flow[X][Father[X]]-=F;
        }
        DistD+=D[Dest];
        CostMaxFlow+=(F*DistD);
    }
    return CostMaxFlow;
}

void Print ()
{
    ofstream fout ("fmcm.out");
    fout << CalculateFlow () << "\n";
    fout.close ();
}

int main()
{
    Read ();
    Print ();
    return 0;
}