Cod sursa(job #2961127)

Utilizator iulia.talpalariuIulia-Georgiana Talpalariu iulia.talpalariu Data 5 ianuarie 2023 21:01:21
Problema Flux maxim de cost minim Scor 70
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.92 kb
#include <vector>
#include <queue>
#include <fstream>
#include <climits>
#include <iostream>

using namespace std;
ifstream fileIn("fmcm.in");
ofstream fileOut("fmcm.out");


class MaxFlowMinCost  {
    int N;
    int M;
    int S;
    int D;
    vector<int> distance;
    vector<int> prev_in_bfs;
    vector<vector<int>> list_adj;
    vector<vector<int>> capacities;
    vector<vector<int>> costs;

public:
    void read();
    void initialize(int k, int initial_capacity = 0);
    int bellman_ford(int& source, int& target);
    int maxflow_mincost();
};

void MaxFlowMinCost::initialize(int k, int initial_capacity) {
    list_adj.resize(k);
    distance.resize(k, INT_MAX);
    prev_in_bfs.resize(k, -1);
    capacities.resize(k);
    costs.resize(k);


    for(int i = 0; i < (int) capacities.size(); ++i) {
        capacities[i].resize(k, 0);
        costs[i].resize(k, 0);
    }
}

void MaxFlowMinCost::read() {
    fileIn >> N >> M >> S >> D;
    initialize(N + 1);

    int a, b, c, d; // c capacitate, d cost
    for( int i = 1; i <= M; i++) {

        fileIn >> a >> b >> c >> d;
        list_adj[a].push_back(b);
        list_adj[b].push_back(a);

        capacities[a][b] = c;
        costs[a][b] = d;
        costs[b][a] = -d;
    }
}

int MaxFlowMinCost::bellman_ford(int &source, int &target) {
    distance.clear();
    distance.resize(N + 1, INT_MAX);

    vector<bool> inQueue(N + 1, false);
    queue<int> q;

    q.push(source);
    distance[source] = 0;
    prev_in_bfs[source] = source;
    inQueue[source] = true;

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


        for (auto neigh: list_adj[node]) {

            if (capacities[node][neigh] > 0 && distance[neigh] > distance[node] + costs[node][neigh]) {
                distance[neigh] = distance[node] + costs[node][neigh];
                prev_in_bfs[neigh] = node;
                if (!inQueue[neigh]) {
                    inQueue[neigh] = true;
                    q.push(neigh);
                }
            }
        }


    }
    int curr_flow = INT_MAX;

    if (distance[target]) {


        for(int curr_node = D; curr_node != S; curr_node = prev_in_bfs[curr_node]) {
            curr_flow = min(curr_flow, capacities[prev_in_bfs[curr_node]][curr_node]);
        }

        for(int curr_node = D; curr_node != S; curr_node = prev_in_bfs[curr_node]) {
            capacities[curr_node][prev_in_bfs[curr_node]] += curr_flow;
            capacities[prev_in_bfs[curr_node]][curr_node] -= curr_flow;
        }
    }

    return curr_flow;
}

int MaxFlowMinCost::maxflow_mincost() {
    int maxflow = 0;
    int bottleneck = bellman_ford(S, D);

    while(bottleneck != 0) { // while i still can find a path with flow on it
        maxflow += bottleneck * distance[D];
        bottleneck = bellman_ford(S, D);
    }
    return maxflow;
}

int main()  {
    MaxFlowMinCost fmcm;
    fmcm.read();
    fileOut << fmcm.maxflow_mincost();

    return 0;
}