Cod sursa(job #2764112)

Utilizator alextodoranTodoran Alexandru Raul alextodoran Data 19 iulie 2021 15:56:22
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.34 kb
/**
 ____ ____ ____ ____ ____
||a |||t |||o |||d |||o ||
||__|||__|||__|||__|||__||
|/__\|/__\|/__\|/__\|/__\|

**/

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N_MAX = 350;

int n, m;

int source, sink;

int cap[N_MAX + 2][N_MAX + 2];
int flow[N_MAX + 2][N_MAX + 2];
int cost[N_MAX + 2][N_MAX + 2];

vector <int> adj[N_MAX + 2];

void addEdge (int u, int v, int ecap, int ecost)
{
    adj[u].push_back(v);
    adj[v].push_back(u);

    cap[u][v] = ecap;
    cap[v][u] = 0;

    flow[u][v] = 0;
    flow[v][u] = 0;

    cost[u][v] = ecost;
    cost[v][u] = -ecost;
}

int prec[N_MAX + 2];

void BellmanFord ()
{
    for(int u = 1; u <= n; u++)
        prec[u] = INT_MAX;

    queue <int> q;

    prec[source] = 0;
    q.push(source);

    while(q.empty() == false)
    {
        int u = q.front();
        q.pop();

        for(int v : adj[u])
            if(cap[u][v] > 0)
            {
                if(prec[u] + cost[u][v] < prec[v])
                {
                    prec[v] = prec[u] + cost[u][v];
                    q.push(v);
                }
            }
    }
}

int dist[N_MAX + 2];
int newPrec[N_MAX + 2];

int parent[N_MAX + 2];
bool visited[N_MAX + 2];

bool Dijkstra ()
{
    for(int u = 1; u <= n; u++)
    {
        parent[u] = -1;
        dist[u] = INT_MAX;
        visited[u] = false;
    }

    priority_queue <pair <int, int>> q;

    dist[source] = 0;
    newPrec[source] = 0;
    parent[source] = 0;
    q.push(make_pair(-dist[source], source));

    while(q.empty() == false)
    {
        int u = q.top().second;
        q.pop();

        if(visited[u] == true)
            continue;
        visited[u] = true;

        for(int v : adj[u])
            if(flow[u][v] < cap[u][v])
            {
                if(dist[u] + ((prec[u] - prec[v]) + cost[u][v]) < dist[v])
                {
                    dist[v] = dist[u] + ((prec[u] - prec[v]) + cost[u][v]);
                    newPrec[v] = newPrec[u] + cost[u][v];
                    parent[v] = u;
                    q.push(make_pair(-dist[v], v));
                }
            }
    }

    for(int u = 1; u <= n; u++)
        prec[u] = newPrec[u];

    return parent[sink] != -1;
}

int minCost ()
{
    int answer = 0;
    while(Dijkstra() == true)
    {
        int push = INT_MAX;
        int sumCost = 0;
        {
            int u = sink;
            while(u != source)
            {
                int v = parent[u];

                push = min(push, cap[v][u] - flow[v][u]);
                sumCost += cost[v][u];

                u = v;
            }
        }

        {
            int u = sink;
            while(u != source)
            {
                int v = parent[u];

                flow[v][u] += push;
                flow[u][v] -= push;

                u = v;
            }
        }

        answer += sumCost * push;
    }

    return answer;
}

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

    fin >> n >> m >> source >> sink;

    for(int it = 1; it <= m; it++)
    {
        int u, v, ecap, ecost;
        fin >> u >> v >> ecap >> ecost;

        addEdge(u, v, ecap, ecost);
    }

    BellmanFord();

    fout << minCost() << "\n";

    return 0;
}