Cod sursa(job #2959558)

Utilizator AdelaCorbeanuAdela Corbeanu AdelaCorbeanu Data 1 ianuarie 2023 13:52:47
Problema Flux maxim de cost minim Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.98 kb
#include <bits/stdc++.h>
using namespace std;

std::vector<int> bellman_ford (std::vector<std::vector<int>> &nodes_list,
                               std::vector<std::vector<int>> &capacity,
                               std::vector<std::vector<int>> &price) {

    int n = nodes_list.size();
    std::vector<int> distances(n + 1, 1e9);
    std::queue<int> updated;
    std::vector<bool> in_queue(n + 1, false);

    distances[0] = 0;
    updated.push(0);
    in_queue[0] = true;

    while (!updated.empty()) {
        int current = updated.front();
        updated.pop();

        in_queue[current] = false;

        for (auto nbh: nodes_list[current]) {
            if (capacity[current][nbh]) {
                if (distances[current] + price[current][nbh] < distances[nbh]) {
                    distances[nbh] = distances[current] + price[current][nbh];

                    if (!in_queue[nbh]) {
                        updated.push(nbh);
                        in_queue[nbh] = true;
                    }
                }
            }
        }
    }

    return distances;
}

int dijkstra (std::vector<std::vector<int>> &nodes_list,
              std::vector<std::vector<int>> &capacity,
              std::vector<std::vector<int>> &price,
              std::vector<int> &initial_distances,
              std::vector<int> &positive_distances,
              std::vector<int> &father,
              int start, int finish,
              int &flow, int &flow_price) {

    int n = nodes_list.size();
    std::vector<int> dist(n, 1e9);

    priority_queue<int, vector<int>, greater<>> heap_dist;

    dist[start] = positive_distances[start] = 0;
    heap_dist.push(start);

    while (!heap_dist.empty()) {
        auto current_node = heap_dist.top();
        heap_dist.pop();

        for (auto nbh : nodes_list[current_node]) {
            if (capacity[current_node][nbh]) {

                int new_dist_to_nbh = dist[current_node] + price[current_node][nbh] + initial_distances[current_node] - initial_distances[nbh];
                if (new_dist_to_nbh < dist[nbh]) {
                    dist[nbh] = new_dist_to_nbh;
                    father[nbh] = current_node;
                    positive_distances[nbh] = positive_distances[current_node] + price[current_node][nbh];
                    heap_dist.push(nbh);
                }
            }
        }
    }

    if (dist[finish] == 1e9) return false;

    int path_capacity = 1e9, path_price = 0;
    int current = finish;
    while (current != start) {
        path_capacity = min(path_capacity, capacity[father[current]][current]);
        path_price += price[father[current]][current];
        current = father[current];
    }

    flow += path_capacity;
    flow_price += path_capacity * positive_distances[finish];

    current = finish;
    while (current != start) {
        capacity[current][father[current]] += path_capacity;
        capacity[father[current]][current] -= path_capacity;
        current = father[current];
    }

    return true;
}

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

    int n, m, start, finish;
    fin >> n >> m >> start >> finish;

    std::vector<std::vector<int>> adj_list(n + 1);
    std::vector<std::vector<int>> capacity(n + 1, std::vector<int>(n + 1, 0));
    std::vector<std::vector<int>> price(n + 1, std::vector<int>(n + 1, 0));

    for (int i = 1; i <= m; ++i) {
        int source, dest, cap, cost;
        fin >> source >> dest >> cap >> cost;

        adj_list[source].push_back(dest);
        adj_list[dest].push_back(source);
        capacity[source][dest] = cap;
        price[source][dest] = cost;
        price[dest][source] = -cost;
    }

    auto initial_distances = bellman_ford(adj_list, capacity, price);
    std::vector<int> positive_distances(n + 1, 1e9);

    int flow = 0, flow_price = 0;

    std::vector<int> father(n + 1, 0);
    while (dijkstra(adj_list, capacity, price, initial_distances, positive_distances, father, start, finish, flow, flow_price));

    fout << flow_price;

    return 0;
}