Cod sursa(job #988841)

Utilizator danalex97Dan H Alexandru danalex97 Data 23 august 2013 23:09:58
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 5.76 kb
/*
#include <algorithm>
#include <fstream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;

typedef struct { int x,c; } node;

struct cmp_node
{
    bool operator () (const node x,const node y)
    {
        return x.c >= y.c;
    }
};

node make_node(int x,int c)
{
    node now;
    now.x = x;
    now.c = c;
    return now;
}

priority_queue<node,vector<node>,cmp_node> Q;

ifstream F("fmcm.in");
ofstream G("fmcm.out");

const int Nmax = 355;
const int Mmax = 12510;
const int value = 1010;

int N,M,D[Nmax];
int capacity[Nmax][Nmax];
int cost[Nmax][Nmax];
vector<int> V[Nmax];
int last[Nmax];
int total_flow,total_cost;

#define IT(type) vector<type>::iterator

int Bellman_pq(int start,int target)
{
    memset(last,0,sizeof(last));
    memset(D,0x3f,sizeof(D));

    D[start] = 0;
    last[start] = -1;
    Q.push( make_node(start,D[start]) );

    while ( Q.size() )
    {
        node now = Q.top();
        Q.pop();

        if ( D[now.x] != now.c )
            continue;

        for (IT(int) it=V[now.x].begin();it!=V[now.x].end();++it)
            if ( capacity[now.x][*it] != 0 )
                if ( D[*it] > D[now.x] + cost[now.x][*it] )
                {
                    D[*it] = D[now.x] + cost[now.x][*it];
                    last[*it] = now.x;
                    Q.push( make_node( *it , D[now.x] + cost[now.x][*it] ) );
                }
    }

    return D[target] != D[0];
}

int main()
{
    F>>N>>M;
    int source = 1;
    int target = N;
    F>>source>>target;
    for (int i=1,x,y,c,cc;i<=M;++i)
    {
        F>>x>>y>>c>>cc;
        if ( capacity[x][y] == 0 && capacity[y][x] == 0 )
        {
            V[ x ].push_back( y );
            V[ y ].push_back( x );
        }
        capacity[x][y] += c;
        cost[x][y] = cc;
        cost[y][x] = -cc;
    }

    while ( Bellman_pq(source,target) != 0 )
    {
        int Cmin = capacity[last[target]][target];
        for (int now=last[target];now!=source;now=last[now])
            Cmin = min( Cmin , capacity[last[now]][now] );

        total_flow += Cmin;

        for (int now=last[target];now!=source;now=last[now])
        {
            capacity[last[now]][now] -= Cmin;
            capacity[now][last[now]] += Cmin;
            total_cost += cost[last[now]][now] * Cmin;
        }
        capacity[last[target]][target] -= Cmin;
        total_cost += cost[last[target]][target] * Cmin;
    }

    G<<total_cost<<'\n';
}
*/

#include <cstdio>
#include <cassert>
#include <cstring>
#include <queue>
#include <vector>

using namespace std;

#define MAXN 355

int N, M, S, D;
int C[MAXN][MAXN], Cst[MAXN][MAXN];
vector<int> con[MAXN];
int F, FCst;

int old_d[MAXN]; char inQ[MAXN];
queue<int> Q;

int d[MAXN], real_d[MAXN], p[MAXN];
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > H;

inline bool dijkstra()
{
    memset(d, 0x3f, sizeof(d));
    d[S] = 0; real_d[S] = 0;
    H.push(make_pair(d[S], S));

    for (; !H.empty(); )
    {
        int cst = H.top().first, nod = H.top().second;
        H.pop();
        if (d[nod] != cst)
            continue;

        vector<int> :: iterator it;
        for (it = con[nod].begin(); it != con[nod].end(); it++)
            if (C[nod][*it])
            {
                int new_d = d[nod] + Cst[nod][*it] + old_d[nod] - old_d[*it];
                if (new_d < d[*it])
                {
                    d[*it] = new_d;
                    real_d[*it] = real_d[nod] + Cst[nod][*it];
                    p[*it] = nod;
                    H.push(make_pair(d[*it], *it));
                }
            }
    }
    memcpy(old_d, real_d, sizeof(d));
    if (d[D] == 0x3f3f3f3f)
        return false;

    int Min = 0x3f3f3f3f, curCst = 0;
    for (int aux = D; aux != S; aux = p[aux])
        Min = min(Min, C[p[aux]][aux]),
        curCst += Cst[p[aux]][aux];

    F += Min;
    FCst += Min * real_d[D];
    for (int aux = D; aux != S; aux = p[aux])
        C[p[aux]][aux] -= Min,
        C[aux][p[aux]] += Min;

    return true;
}

inline bool bellmanFord()
{
    memset(old_d, 0x3f, sizeof(old_d));
    old_d[S] = 0;

    for (Q.push(S), inQ[S] = 1; !Q.empty(); Q.pop())
    {
        vector<int> :: iterator it;
        int i = Q.front();
        inQ[i] = 0;

        for (it = con[i].begin(); it != con[i].end(); it++)
            if (C[i][*it])
            {
                if (old_d[i] + Cst[i][*it] >= old_d[*it])
                    continue;

                old_d[*it] = old_d[i] + Cst[i][*it];
                if (inQ[*it])
                    continue;

                inQ[*it] = 1;
                Q.push(*it);
            }
    }

    if (old_d[D] == 0x3f3f3f3f)
        return false;

    return true;
}

int main()
{
    freopen("fmcm.in", "rt", stdin);
    freopen("fmcm.out", "wt", stdout);

    assert(scanf("%d %d %d %d", &N, &M, &S, &D) == 4);
    assert(1 <= N && N <= 350);
    assert(1 <= M && M <= 12500);
    assert(1 <= S && S <= N);
    assert(1 <= D && D <= N);
    assert(S != D);

    for (; M; M--)
    {
        int x, y;
        assert(scanf("%d %d ", &x, &y) == 2);
        assert(1 <= x && x <= N);
        assert(1 <= y && y <= N);
        assert(x != y && !C[x][y] && !Cst[x][y] && !C[y][x] && !Cst[y][x]);
        assert(x != D && y != S);
        con[x].push_back(y);
        con[y].push_back(x);

        assert(scanf("%d %d", C[x] + y, Cst[x] + y) == 2);
        assert(1 <= C[x][y] && C[x][y] <= 10000);
        assert(-1000 <= Cst[x][y] && Cst[x][y] <= 1000);
        Cst[y][x] = -Cst[x][y];
    }

    F = FCst = 0;
    bellmanFord();
    for (; dijkstra(); );

    printf("%d\n", FCst);
    return 0;
}