Cod sursa(job #2961452)

Utilizator Katherine456719Swan Katherine Katherine456719 Data 6 ianuarie 2023 15:26:31
Problema Flux maxim de cost minim Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.78 kb
#include<iostream>
#include <fstream>
#include <vector>
#include <queue>

using namespace std;
const int inf = 1e9;
int n, m, sursa, dest;
vector<vector<int>> graf;
int capacitate[400][400];
int cost[400][400];//costul muchiei i,j
int distanta[400];//distanta dela sursa la nodul i
int new_dist[400];
bool in_coada[400];
vector<int> parinte;

// aplicam algoritmul lui Bellman-Ford,
// calculam valorile vectorului dist.
// petru a folosi dijkstra astfel:
// calculam distanta minima de la sursa la nodul i
// ficarui arc a->b cu costul c va avea noul cost
// c + dist a - dist b astfel incat sa
// nu mai exista arce cu cost negativ

void aflare_distanta_minima() {
    for (int i = 1; i <= n; ++i)
        distanta[i] = inf;

    distanta[sursa] = 0;
    queue<int> q;
    q.push(sursa);
    in_coada[sursa] = true;

    while (!q.empty()) {
        int curr = q.front();
        q.pop();
        in_coada[curr] = false;

        for (int node: graf[curr]) {
            if (capacitate[curr][node] != 0) {
                if (distanta[curr] + cost[curr][node] < distanta[node]) {
                    distanta[node] = distanta[curr] + cost[curr][node];
                    if (!in_coada[node]) {
                        q.push(node);
                        in_coada[node] = true;
                    }
                }
            }
        }
    }
}

void flux(int &cflux, int &ccost) {
    for (int i = 1; i <= n; ++i) {
        parinte[i] = -1;
        new_dist[i] = inf;
    }
    //             distanta, nod
    priority_queue<pair<int, int>> q;
    q.push({0, sursa});
    new_dist[sursa] = 0;
    parinte[sursa] = 0;

    while (!q.empty()) {
        int curr_dist = -q.top().first;
        int curr_node = q.top().second;
        q.pop();

        if (curr_dist != new_dist[curr_node])
            continue;

        for (int node: graf[curr_node]) {
            if (capacitate[curr_node][node] != 0) {
                int dist = cost[curr_node][node] + distanta[curr_node] - distanta[node];
                int dist_c = curr_dist + dist;
                if (dist_c < new_dist[node]) {
                    new_dist[node] = dist_c;
                    parinte[node] = curr_node;
                    q.push({-dist_c, node});
                }
            }
        }
    }

    int c = 0;
    int flux = inf;

    if (parinte[dest] != -1) {
        int node = dest;
        while (node != sursa) {
            flux = min(flux, capacitate[parinte[node]][node]);
            c += cost[parinte[node]][node];
            node = parinte[node];
        }
        node = dest;
        while (node != sursa) {
            capacitate[node][parinte[node]] += flux;
            capacitate[parinte[node]][node] -= flux;
            node = parinte[node];
        }
        for (int i = 1; i <= n; ++i)
            distanta[i] = new_dist[i];

        cflux = flux;
        ccost = c * flux;
    } else {
        cflux = 0;
        ccost = 0;
    }
}


int main() {
    ifstream fin("fmcm.in");
    ofstream fout("fmcm.out");
    fin >> n >> m >> sursa >> dest;
    graf.resize(n + 1);
    parinte.resize(n + 1);
    //initializare lista de adiacenta, capacitate si cost
    while (m--) {
        int x, y, cap, cos;
        fin >> x >> y >> cap >> cos;
        cost[x][y] = cos;
        cost[y][x] = -cos;

        capacitate[x][y] = cap;
        capacitate[y][x] = 0;

        graf[x].push_back(y);
        graf[y].push_back(x);
    }

    //calculam fluxum maxim de cost minim
    aflare_distanta_minima();
    int current_flux = 0, current_cost = 0, total_cost = 0;
    do {
        flux(current_flux, current_cost);
        total_cost += current_cost;
    } while (current_flux);
    fout << total_cost << "\n";
    return 0;
}