Cod sursa(job #3040846)

Utilizator lucametehauDart Monkey lucametehau Data 30 martie 2023 15:08:21
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.66 kb
#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <cstring>
#include <chrono>
#include <cassert>
#include <bitset>
#include <stack>
#include <queue>
#include <iomanip>
#include <random>
#include <string>
#include <complex>
#include <algorithm>
#include <numeric>
#include <immintrin.h>

#ifdef _MSC_VER
#  include <intrin.h>
#  define __builtin_popcount __popcnt
#  define __builtin_popcountll __popcnt64
#endif

#pragma warning(disable : 4996)

//#pragma GCC optimize("Ofast")
#define x first
#define y second
#define ld long double
#define ll long long
#define ull unsigned long long
#define us unsigned short
#define lsb(x) ((x) & (-(x)))
#define pii pair <int, int>
#define pll pair <ll, ll>

using namespace std;

//const int MOD = (int)1e9 + 7;

mt19937_64 gen(chrono::duration_cast<chrono::nanoseconds>(chrono::steady_clock::now().time_since_epoch()).count());
uniform_int_distribution <int> rng;
const ld PI = acos(-1);

const int MOD = (int)1e9 + 7;

struct Edge {
    int to, cap, ind, cost;
};

class MaxFlow {
public:
    vector <vector <Edge>> g;
    vector <int> dist;
    vector <int> lst;

    void init(int n) {
        g.resize(n + 1);
        dist.resize(n + 1);
        lst.resize(n + 1);
    }

    void add_edge(int x, int y, int cap, int cost) {
        g[x].push_back({ y, cap, (int)g[y].size(), cost });
        g[y].push_back({ x, 0, (int)g[x].size() - 1, -cost });
    }

    int bfs(int src, int dst) {
        queue <int> q;
        fill(dist.begin(), dist.end(), (int)1e9);
        fill(lst.begin(), lst.end(), 0);
        dist[src] = 0;
        q.push(src);

        while (!q.empty()) {
            int node = q.front();
            q.pop();
            for (auto& [son, cap, ind, cost] : g[node]) {
                if (cap > 0 && dist[son] > cost + dist[node]) {
                    dist[son] = cost + dist[node];
                    lst[son] = ind;
                    q.push(son);
                }
            }
        }

        if (dist[dst] == (int)1e9)
            return 0;

        return dist[dst];
    }

    pii min_cost_max_flow(int src, int dst) {
        int cost, max_flow = 0, min_cost = 0;
        while (cost = bfs(src, dst)) {
            int flow = (int)1e9, node = dst;
            while (node != src) {
                int prev_node = g[node][lst[node]].to;
                flow = min(flow, g[prev_node][g[node][lst[node]].ind].cap);
                node = prev_node;
            }
            node = dst;
            while (node != src) {
                int prev_node = g[node][lst[node]].to;
                g[prev_node][g[node][lst[node]].ind].cap -= flow;
                g[node][lst[node]].cap += flow;
                node = prev_node;
            }

            max_flow += flow;
            min_cost += flow * cost;
        }

        return { max_flow, min_cost };
    }
} network;

void solve(int test = 0) {
    int n, m, src, dst;
    cin >> n >> m >> src >> dst;
    network.init(n);

    for (; m; m--) {
        int x, y, z, c;
        cin >> x >> y >> z >> c;
        network.add_edge(x, y, z, c);
    }

    cout << network.min_cost_max_flow(src, dst).y << "\n";
}

int main() {
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    srand(time(0));

#ifdef LOCAL
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#else
    freopen("fmcm.in", "r", stdin);
    freopen("fmcm.out", "w", stdout);
#endif

    int T = 1;

    //cin >> T;

    for (int t = 1; t <= T; t++) {
        solve(t);
    }

    return 0;
}