Cod sursa(job #3189639)

Utilizator annna7Pecheanu Anna annna7 Data 6 ianuarie 2024 12:45:52
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.24 kb
#include <fstream>
#include <vector>
#include <queue>
#include <climits>
#include <map>
#include <iostream>

using namespace std;

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

struct Edge {
    int to;
    int flow;
    int capacity;
    int cost;
    int reverse;
};

class Network {
    int V;
    int source, sink;
    vector<int> parent;
    vector<int> dist;
    vector<vector<Edge>> adj;
public:
    Network(int V, int source = -1, int sink = -1) {
        this->V = V;
        this->source = source == -1 ? 0 : source;
        this->sink = sink == -1 ? V - 1 : sink;
        adj.resize(V);
        dist.resize(V, INT_MAX);
        parent.resize(V, -1);
    }

    void addEdge(int u, int v, int capacity, int cost) {
        Edge a{v, 0, capacity, cost,(int)adj[v].size()};
        Edge b{u, 0, 0, -cost, (int)adj[u].size()};

        adj[u].push_back(a);
        adj[v].push_back(b);
    }

    bool dijkstra();
    int DFS(int node, int bottleneck, int t);
    int getMaxFlow();
    int getCostForMaxFlow(int node, int flow);
};

bool Network::dijkstra() {
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq;
    dist.assign(V, INT_MAX);
    dist[source] = 0;
    pq.emplace(0, source);

    while (!pq.empty()) {
        int currDistance = pq.top().first;
        int currNode = pq.top().second;
        pq.pop();

        if (currDistance != dist[currNode]) continue;

        for (auto &edge : adj[currNode]) {
            if (edge.flow < edge.capacity && dist[currNode] != INT_MAX && dist[edge.to] > dist[currNode] + edge.cost) {
                dist[edge.to] = dist[currNode] + edge.cost;
                parent[edge.to] = currNode;
                if (edge.to != sink) {
                    pq.emplace(dist[edge.to], edge.to);
                }
            }
        }
    }

    return dist[sink] != INT_MAX;
}


int Network::getCostForMaxFlow(int node, int flow) {
    int totalCost = 0, bottleneck = INT_MAX;

    while (dijkstra()) {
        for (int v = sink; v != source; v = parent[v]) {
            int u = parent[v];
            for(auto &edge : adj[u]){
                if(edge.to == v){
                    bottleneck = min(bottleneck, edge.capacity - edge.flow);
                    break;
                }
            }
        }

        for (int v = sink; v != source; v = parent[v]) {
            int u = parent[v];
            for(auto &edge : adj[u]){
                if(edge.to == v){
                    edge.flow += bottleneck;
                    adj[v][edge.reverse].flow -= bottleneck;
                    totalCost += edge.cost * bottleneck;
                    break;
                }
            }
        }
    }

   return totalCost;
}

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

    int source = 2*n, sink = 2*n + 1;
    Network network(2*n + 2, source, sink);

    int x;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; ++j) {
            fin >> x;
            network.addEdge(i, j + n, 1, x);
        }
    }

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

    fout << network.getCostForMaxFlow(0, INT_MAX) << "\n";
}