Cod sursa(job #3188379)

Utilizator LazarDanielGabrielLazar Daniel-Gabriel LazarDanielGabriel Data 2 ianuarie 2024 19:20:05
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.59 kb
#include <fstream>
#include <climits>
#include <vector>
#include <queue>

using namespace std;

ifstream inputFile("cc.in");   // Deschiderea fișierului de intrare
ofstream outputFile("cc.out"); // Deschiderea fișierului de ieșire

// Structura pentru a reprezenta o muchie în graf
struct Edge {
    int destination, flow, capacity, cost, reverseEdgeIndex;
};

vector<vector<Edge>> graph; // Graful reprezentat ca un vector de vectori de Edge

// Funcție pentru adăugarea unei muchii în graf
void addEdge(int from, int to, int capacity, int cost) {
    graph[from].push_back({to, 0, capacity, cost, static_cast<int>(graph[to].size())});
    graph[to].push_back({from, 0, 0, -cost, static_cast<int>(graph[from].size()) - 1});
}

// Funcția principală pentru calculul fluxului minim cu cost minim
int minCostFlow(int source, int sink) {
    int totalCost = 0;

    while (true) {
        priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> minHeap;
        vector<int> distance(graph.size(), INT_MAX);
        vector<pair<int, int>> parent(graph.size());

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

        while (!minHeap.empty()) {
            int currentDistance = minHeap.top().first;
            int currentNode = minHeap.top().second;

            minHeap.pop();

            if (currentDistance > distance[currentNode])
                continue;

            for (size_t i = 0; i < graph[currentNode].size(); ++i) {
                int capacity = graph[currentNode][i].capacity;
                int flow = graph[currentNode][i].flow;
                int cost = graph[currentNode][i].cost;
                int neighbor = graph[currentNode][i].destination;

                if (capacity - flow > 0 && distance[currentNode] < INT_MAX && distance[neighbor] > distance[currentNode] + cost) {
                    distance[neighbor] = distance[currentNode] + cost;
                    minHeap.push({distance[neighbor], neighbor});
                    parent[neighbor] = {currentNode, static_cast<int>(i)};
                }
            }
        }

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

        int bottleneck = INT_MAX;
        for (int current = sink; current != source; current = parent[current].first) {
            int previous = parent[current].first;
            int edgeIndex = parent[current].second;
            bottleneck = min(bottleneck, graph[previous][edgeIndex].capacity - graph[previous][edgeIndex].flow);
        }

        for (int current = sink; current != source; current = parent[current].first) {
            int previous = parent[current].first;
            int edgeIndex = parent[current].second;

            graph[previous][edgeIndex].flow += bottleneck;
            graph[current][graph[previous][edgeIndex].reverseEdgeIndex].flow -= bottleneck;
            totalCost += bottleneck * graph[previous][edgeIndex].cost;
        }
    }

    return totalCost;
}

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

    graph.resize(2 * n + 2);

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

    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            int edgeCost;
            inputFile >> edgeCost;
            addEdge(i, j + n, 1, edgeCost);
        }
    }

    outputFile << minCostFlow(source, sink);

    inputFile.close();    // Închiderea fișierului de intrare
    outputFile.close();   // Închiderea fișierului de ieșire

    return 0;
}