Cod sursa(job #2959531)

Utilizator AdelaCorbeanuAdela Corbeanu AdelaCorbeanu Data 31 decembrie 2022 17:33:08
Problema Flux maxim de cost minim Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.51 kb
#include <bits/stdc++.h>
using namespace std;

std::vector<std::vector<int>> adj_list;
std::vector<std::vector<int>> capacity;
std::vector<std::vector<int>> price;
std::vector<int> initial_distances;
std::vector<int> positive_distances;

int flow = 0, flow_price = 0;

int n, m, start, finish;

std::vector<int> bellman_ford () {

    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: adj_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<int> dist(n + 1, 1e9);
    std::vector<int> father(n + 1, 0);

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

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

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

        if (dist[current_node] != current_price) continue;

        for (auto nbh : adj_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, dist[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");

    fin >> n >> m >> start >> finish;

    adj_list.resize(n + 1);
    capacity.resize(n + 1, std::vector<int>(n + 1, 0));
    price.resize(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;
    }

    initial_distances = bellman_ford();
    positive_distances.resize(n + 1, 1e9);

    while (dijkstra());

    fout << flow_price;

    return 0;
}