Cod sursa(job #1585292)

Utilizator Ionut.popescuLiviu Rebreanu Ionut.popescu Data 30 ianuarie 2016 21:58:36
Problema Flux maxim de cost minim Scor 40
Compilator cpp Status done
Runda Arhiva educationala Marime 3.31 kb
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 350 + 50;
const int MAX_M = 12500 + 50;
const int NIL = -1;
const int INF = numeric_limits <int> :: max() / 2;

struct Edge
{
    int v;
    int cap, cost;
    int next;
};

Edge G[2 * MAX_M];
int head[MAX_N];

int D[MAX_N];
bool inQueue[MAX_N];
int Q[MAX_N];
int qStart, qEnd;

int N;
int source, sink;

void addEdge(int u, int v, int cap, int cost, int pos)
{
    G[pos] = { v, cap, cost, head[u] };
    head[u] = pos;
}

void SPFA()
{
    Q[0] = source;
    qStart = 0; qEnd = 1;

    for ( int i = 0; i < N; i++ )
        D[i] = INF;

    D[source] = 0;

    while ( qStart != qEnd )
    {
        int u = Q[qStart++];

        inQueue[u] = 0;

        for ( int i = head[u]; i != NIL; i = G[i].next )
        {
            int v = G[i].v;

            if ( G[i].cap > 0 && D[u] + G[i].cost < D[v] )
            {
                D[v] = D[u] + G[i].cost;

                if ( !inQueue[v] )
                {
                    inQueue[v] = 1;
                    Q[qEnd++] = v;
                }
            }
        }
    }

    for ( int i = 0; i < N; i++ )
        D[i] = D[sink] - D[i];
}

int augment(int u, int flow)
{
    if ( u == sink )
        return flow;

    inQueue[u] = 1;

    int ret = flow;

    for ( int i = head[u]; i != NIL; i = G[i].next )
    {
        int v = G[i].v;

        if ( G[i].cap && !inQueue[v] && D[v] + G[i].cost == D[u] )
        {
            int newFlow = augment( v, min( G[i].cap, ret ) );

            G[i].cap     -= newFlow;
            G[i ^ 1].cap += newFlow;

            ret -= newFlow;

            if ( !ret )
                return flow;
        }
    }
    return flow - ret;
}

bool adjust()
{
    int delta = INF;

    for ( int u = 0; u < N; u++ )
    {
        if ( inQueue[u] )
        {
            for ( int i = head[u]; i != NIL; i = G[i].next )
            {
                int v = G[i].v;

                if ( G[i].cap > 0 && !inQueue[v] )
                    delta = min( delta, D[v] + G[i].cost - D[u] );
            }
        }
    }

    if ( delta == INF )
        return 0;

    for ( int i = 0; i < N; i++ )
        if ( inQueue[i] )
            D[i] += delta;

    for ( int i = 0; i < N; i++ )
        inQueue[i] = 0;

    return 1;
}

int main()
{
    ifstream in("fmcm.in");
    in.tie(0);
    ios_base::sync_with_stdio(false);
    int M;

    in >> N >> M >> source >> sink;
    source--; sink--;

    for ( int i = 0; i < N; i++ )
        head[i] = NIL;

    for ( int i = 0; i < M; i++ )
    {
        int u, v, cost, cap;

        in >> u >> v >> cap >> cost;

        addEdge( u - 1, v - 1, cap, cost, 2 * i );
        addEdge( v - 1, u - 1, 0, -cost, 2 * i + 1 );
    }

    int tmp, flow = 0;

    SPFA();

    do
    {
        tmp = 0;

        do
        {
            for ( int i = 0; i < N; i++ )
                inQueue[i] = 0;

            tmp = augment( source, INF );
            flow += tmp;

        } while ( tmp );

    } while ( adjust() );

    int cost = 0;

    for ( int i = 0; i < M; i++ )
        cost += G[2 * i + 1].cap * G[2 * i].cost;

    ofstream out("fmcm.out");
    out << cost << '\n';
    out.close();
    return 0;
}