Cod sursa(job #3187624)

Utilizator marius004scarlat marius marius004 Data 29 decembrie 2023 18:40:06
Problema Cc Scor 10
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.69 kb
#include <fstream>
#include <climits>
#include <vector>
#include <queue>

using namespace std;

ifstream fin("cc.in");
ofstream fout("cc.out");

struct Edge {
    int to, flow, capacity, cost, residual;
};

vector<vector<Edge>> network;

void add_edge(int u, int v, int capacity, int cost) {
    network[u].push_back({v, 0, capacity, cost, (int) network[v].size()});
    network[v].push_back({u, 0, 0, -cost, (int) network[u].size() - 1});
}

int min_cost_flow(int source, int sink) {
    int answer = 0;

    while (true) {
        vector<int> distance (network.size(), INT_MAX);
        vector<pair<int, int>> from (network.size());

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

        pq.push({0, source});
        distance[source] = 0;

        while (!pq.empty()) {
            int dist = pq.top().first;
            int u = pq.top().second;

            pq.pop();

            if (dist != distance[u])
                continue; 

            for (int i = 0;i < network[u].size(); ++i) {
                int capacity = network[u][i].capacity;
                int residual = network[u][i].residual;
                int flow = network[u][i].flow;
                int cost = network[u][i].cost;
                int v = network[u][i].to;

                if (capacity - flow > 0 && distance[u] < INT_MAX && distance[u] + cost < distance[v]) {
                    distance[v] = distance[u] + cost;
                    pq.push({distance[v], v});
                    from[v] = {u, i};
                }
            }
        }

        if (distance[sink] == INT_MAX)
            break; 

        int bottleneck = INT_MAX;
        for (int node = sink; node != source; node = from[node].first) {
            int u = from[node].first;
            int v = from[node].second;
            bottleneck = min(bottleneck, network[u][v].capacity - network[u][v].flow);
        }

        for (int node = sink; node != source; node = from[node].first) {
            int u = from[node].first;
            int v = from[node].second;

            network[u][v].flow += bottleneck; 
            network[v][network[u][v].residual].flow -= bottleneck;
            answer += bottleneck * network[u][v].cost; 
        }
    }

    return answer;
}

int main() {
    int n;
    fin >> n;

    network.resize(2 * n + 2);

    int source = 2 * n, sink = 2 * n + 1;
    for (int i = 0;i < n; ++i) {
        add_edge(source, i, 1, 0);
        add_edge(i + n, sink, 1, 0);
    }

    for (int i = 0;i < n;++i) {
        for (int j = 0;j < n;++j) {
            int cost; 
            fin >> cost; 
            add_edge(i, j + n, 1, cost);
        }
    }

    fout << min_cost_flow(source, sink);

    fin.close();
    fout.close();

    return 0;
}