Cod sursa(job #3233275)

Utilizator MirceaDonciuLicentaLicenta Mircea Donciu MirceaDonciuLicenta Data 2 iunie 2024 21:16:21
Problema Flux maxim de cost minim Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.68 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 (bellmanFord(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 bellmanFord(int s, int t) {
        fill(dist.begin(), dist.end(), INF);
        dist[s] = 0;
        bool improved;
        for (int i = 0; i < graph.size(); ++i) {
            improved = false;
            for (int u = 0; u < graph.size(); ++u) {
                for (int j = 0; j < graph[u].size(); ++j) {
                    Edge &e = graph[u][j];
                    if (e.capacity > e.flow && dist[e.to] > dist[u] + e.cost) {
                        dist[e.to] = dist[u] + e.cost;
                        prev_vertex[e.to] = u;
                        prev_edge[e.to] = j;
                        improved = true;
                    }
                }
            }
            if (!improved) break;
        }
        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;
}