Cod sursa(job #1867199)

Utilizator msciSergiu Marin msci Data 3 februarie 2017 20:39:43
Problema Flux maxim de cost minim Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 5.21 kb
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <string>
#include <sstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <random>
#include <tuple>
#include <limits>
#include <functional>
#include <complex>
#include <bitset>
#include <list>

//#include <atomic>
//#include <condition_variable>
//#include <future>
//#include <mutex>
//#include <thread>

using namespace std;

#define debug(x) cerr << #x << " = " << x << "\n"

struct MinCostFlow
{
    typedef int Cost; typedef int Flow; typedef int Index;

    static const Cost InfCost = 0x3f3f3f3f;
    static const Flow InfCapacity = 0x3f3f3f3f;

    struct Edge
    {
        Index to, rev;
        Flow capacity;
        Cost cost;
    };

    vector< vector<Edge> > g;

    void init(Index n) { g.assign(n, vector<Edge>()); }

    void add(Index i, Index j, Flow capacity = InfCapacity, Cost cost = Cost())
    {
        Edge e, f;
        e.to = j, f.to = i;
        e.capacity = capacity, f.capacity = 0;
        e.cost = cost, f.cost = -cost;
        g[i].push_back(e), g[j].push_back(f);
        g[i].back().rev = (int) g[j].size() - 1;
        g[j].back().rev = (int) g[i].size() - 1;
    }

    void addB(Index i, Index j, Flow capacity = InfCapacity, Cost cost = Cost())
    {
        add(i, j, capacity, cost);
        add(j, i, capacity, cost);
    }

    pair<Cost, Flow> min_cost_max_flow(Index s, Index t, Flow f = InfCapacity, bool useSPFA = false)
    {
        int n = (int) g.size();
        vector<Cost> dist(n);
        vector<Cost> potential(n);
        vector<Index> prev(n);
        vector<Index> prev_edge(n);
        pair<Cost, Flow> total = {0, 0};

        while (f > 0)
        {
            fill(dist.begin(), dist.end(), InfCost);
            if (useSPFA || total.second == 0)
            {
                deque<Index> q;
                q.push_back(s);
                dist[s] = 0;
                vector<bool> in_queue(n);
                while (!q.empty())
                {
                    Index i = q.front();
                    q.pop_front();
                    in_queue[i] = false;
                    for (Index ei = 0; ei < (int) g[i].size(); ei++)
                    {
                        const Edge& e = g[i][ei];
                        Index j = e.to;
                        Cost d = dist[i] + e.cost;
                        if (e.capacity > 0 && d < dist[j])
                        {
                            if (!in_queue[j])
                            {
                                in_queue[j] = true;
                                q.push_back(j);
                            }
                            dist[j] = d;
                            prev[j] = i;
                            prev_edge[j] = ei;
                        }
                    }
                }
            }
            else
            {
                vector<bool> visited(n);
                priority_queue< pair<Cost, Flow> > q;
                q.push({-0, s}); 
                dist[s] = 0;
                while (!q.empty())
                {
                    Index i = q.top().second;
                    q.pop();
                    if (visited[i]) continue;
                    visited[i] = true;
                    for (Index ei = 0; ei < (int) g[i].size(); ei++)
                    {
                        const Edge& e = g[i][ei];
                        if (e.capacity <= 0) continue;
                        Index j = e.to;
                        Cost d = dist[i] + (e.cost + potential[i] - potential[j]);
                        if (dist[j] > d)
                        {
                            dist[j] = d;
                            prev[j] = i;
                            prev_edge[j] = ei;
                            q.push({-d, j});
                        }
                    }
                }
            }
            if (dist[t] == InfCost) break;
            if (!useSPFA) for (Index i = 0; i < n; i++) potential[i] += dist[i];

            Flow d = f; 
            Cost dist_t = 0;
            
            for (Index v = t; v != s; )
            {
                Index u = prev[v];
                const Edge& e = g[u][prev_edge[v]];
                d = min(d, e.capacity); 
                dist_t += e.cost;
                v = u;
            }
            f -= d;
            total.first += d * dist_t;
            total.second += d;
            for (Index v = t; v != s; v = prev[v])
            {
                Edge& e = g[prev[v]][prev_edge[v]];
                e.capacity -= d;
                g[e.to][e.rev].capacity += d;
            }
        }
        return total;
    }
};

const int MinCostFlow::InfCost;
const int MinCostFlow::InfCapacity;

int main(int argc, char* argv[]) 
{
    //freopen("fmcm.in", "r", stdin);
    //freopen("fmcm.out", "w", stdout);
    cin.sync_with_stdio(false);
    int n, m, s, t;
    cin >> n >> m >> s >> t;
    s--, t--;
    MinCostFlow mf; mf.init(n);
    for (int i = 0; i < m; i++)
    {
        int x, y, c, z;
        cin >> x >> y >> c >> z;
        x--, y--;
        mf.add(x, y, c, z);
    }
    auto ans = mf.min_cost_max_flow(s, t);
    cout << ans.first << "\n";
    return 0;
}