Cod sursa(job #1866043)

Utilizator ancabdBadiu Anca ancabd Data 2 februarie 2017 15:36:13
Problema Flux maxim de cost minim Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.42 kb
#include<cstdio>
#include<vector>
#include<queue>
#include<utility>
#include<bitset>
#include<fstream>

using namespace std;

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

#define N 350
#define MULT 2000000000

class mazi
{
    public:
        int nod,cost;

    bool operator < (const mazi a) const{
        return (cost>a.cost);
    }

    bool operator > (const mazi a) const{
        return (cost<a.cost);
    }
};

priority_queue<mazi> heap;

vector < pair<int, int> > vecin[N+1];
queue <int> Q;
bitset <N+1> mark;

int dist[N+1], old[N+1], realD[N+1], viz[N+1], n, S,D;
int c[N+1][N+1], f[N+1][N+1], R, ans, tata[N+1];
bool in_queue[N+1];

bool adauga(int x)
{
    if (viz[x] == n) return false;
    viz[x]++;

    if (in_queue[x] == false)
    {
        Q.push(x);
        in_queue[x] = true;
    }

    return true;
}

bool bellmanford(int nod)
{
    adauga(nod);
    old[nod]=0;

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

        for(unsigned int i = 0; i < vecin[nod].size(); i++)
        {
            int now = vecin[nod][i].first, cost = vecin[nod][i].second;

            if (old[nod] + cost < old[now] && c[nod][now] != 0)
            {
                old[now] = old[nod] + cost;
                if (!adauga(now)) return false;
            }
        }
    }

    return true;
}

mazi make_mazi(int nod,int cost)
{
    mazi a;

    a.nod=nod;
    a.cost=cost;

    return a;
}

bool dijkstra()
{
    int nod = S;
    mark.reset();

    while(!heap.empty()) heap.pop();
    for(int i = 1; i <= n; i++)
    {
        dist[i] = MULT;
        realD[i] = 0;
    }

    dist[nod] = 0;
    heap.push(make_mazi(nod,dist[nod]));

    while(!heap.empty())
    {
        nod = heap.top().nod;
        heap.pop();
        mark.set(nod);

        for(unsigned int i = 0; i < vecin[nod].size(); i++)
        {
            int now = vecin[nod][i].first, cost = vecin[nod][i].second;

            if (dist[now] > dist[nod] + old[nod] + cost - old[now] && c[nod][now] - f[nod][now] > 0)
            {
                dist[now] = dist[nod] + old[nod] + cost - old[now];
                realD[now] = realD[nod] + cost;
                tata[now] = nod;
                heap.push(make_mazi(now,dist[now]));
            }
        }

        while(!heap.empty() && mark[heap.top().nod] == true) heap.pop();
    }

    for(int i = 1; i <= n; i++)old[i] = realD[i];

    return mark[D];
}

void flux()
{
    int mn;

    while (dijkstra())
    {
        int nod = D;
        mn = c[tata[nod]][nod]-f[tata[nod]][nod];

        while (nod != S)
        {
            mn = min(mn, c[tata[nod]][nod] - f[tata[nod]][nod]);
            nod = tata[nod];
        }

        R += mn;
        ans += (mn*realD[D]);
        nod = D;
        while (nod != S)
        {
            f[tata[nod]][nod] += mn;
            f[nod][tata[nod]] -= mn;
            nod = tata[nod];
        }
    }
}

int main()
{
    int m;

    fin >> n >> m >> S >> D;

    for(int i = 1; i <= m; i++)
    {
        int x, y, z, w;
        fin >> x >> y >> w >> z;

        vecin[x].push_back(make_pair(y,z));
        vecin[y].push_back(make_pair(x,-z));

        c[x][y] = w;
    }

    for(int i = 1; i <= n; i++)old[i] = MULT;

    bellmanford(S);

    flux();

    fout << ans;
    return 0;
}