Cod sursa(job #3233277)

Utilizator MirceaDonciuLicentaLicenta Mircea Donciu MirceaDonciuLicenta Data 2 iunie 2024 21:18:15
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.9 kb
#include <iostream>
#include <vector>
#include <queue>
#include <climits>
#include <fstream>

using namespace std;

const int INF = INT_MAX;

struct Edge {
    int to, capacity, cost, flow, reverse_index;
};

class MinCostMaxFlow {
public:
    MinCostMaxFlow(int n) : graph(n), potential(n, 0), dist(n), prev_vertex(n), prev_edge(n) {}

    void addEdge(int u, int v, int capacity, int cost) {
        graph[u].emplace_back(Edge{v, capacity, cost, 0, (int) graph[v].size()});
        graph[v].emplace_back(Edge{u, 0, -cost, 0, (int) graph[u].size() - 1});
    }

    pair<int, int> getMinCostMaxFlow(int s, int t) {
        int flow = 0, cost = 0;
        while (dijkstra(s, t)) {
            int pushed_flow = INF;
            for (int v = t; v != s; v = prev_vertex[v]) {
                pushed_flow = min(pushed_flow, graph[prev_vertex[v]][prev_edge[v]].capacity - graph[prev_vertex[v]][prev_edge[v]].flow);
            }
            for (int v = t; v != s; v = prev_vertex[v]) {
                graph[prev_vertex[v]][prev_edge[v]].flow += pushed_flow;
                graph[v][graph[prev_vertex[v]][prev_edge[v]].reverse_index].flow -= pushed_flow;
                cost += pushed_flow * graph[prev_vertex[v]][prev_edge[v]].cost;
            }
            flow += pushed_flow;
        }
        return {flow, cost};
    }

private:
    vector<vector<Edge>> graph;
    vector<int> potential, dist, prev_vertex, prev_edge;

    bool dijkstra(int s, int t) {
        fill(dist.begin(), dist.end(), INF);
        dist[s] = 0;
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
        pq.push({0, s});

        while (!pq.empty()) {
            int d = pq.top().first;
            int u = pq.top().second;
            pq.pop();

            if (d != dist[u]) continue;

            for (int i = 0; i < graph[u].size(); ++i) {
                Edge &e = graph[u][i];
                int new_dist = dist[u] + e.cost + potential[u] - potential[e.to];
                if (e.capacity > e.flow && new_dist < dist[e.to]) {
                    dist[e.to] = new_dist;
                    prev_vertex[e.to] = u;
                    prev_edge[e.to] = i;
                    pq.push({new_dist, e.to});
                }
            }
        }

        for (int i = 0; i < dist.size(); ++i) {
            if (dist[i] < INF) potential[i] += dist[i];
        }

        return dist[t] != INF;
    }
};

int main() {
    ifstream infile("fmcm.in");
    ofstream outfile("fmcm.out");

    int N, M, S, D;
    infile >> N >> M >> S >> D;

    MinCostMaxFlow mcmf(N);

    for (int i = 0; i < M; ++i) {
        int x, y, c, z;
        infile >> x >> y >> c >> z;
        mcmf.addEdge(x - 1, y - 1, c, z);
    }

    auto result = mcmf.getMinCostMaxFlow(S - 1, D - 1);
    outfile << result.second << endl;

    infile.close();
    outfile.close();

    return 0;
}