Cod sursa(job #3178634)

Utilizator bogdanvladmihaiBogdan Vlad-Mihai bogdanvladmihai Data 2 decembrie 2023 00:19:47
Problema Cc Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.37 kb
#include <bits/stdc++.h>
using namespace std;

const int INF = numeric_limits<int>::max() / 2;
struct Edge {
  int to, flow, capacity, cost, reverse;
};

class WeightedNetwork {
public:
  WeightedNetwork(int N, int source, int sink) : source(source), sink(sink), G(N) {}
  void add_edge(int u, int v, int capacity, int cost) {
    G[u].push_back({v, 0, capacity, cost, (int)G[v].size()});
    G[v].push_back({u, 0, 0, -cost, (int)G[u].size() - 1});
  }
  int min_cost_flow(int flow = INF) {
    int N = G.size();
    vector<int> dist(N), prev(N), prev_edge(N);
    int total_flow = 0, total_cost = 0;
    while (total_flow < flow) {
      fill(dist.begin(), dist.end(), INF);
      dist[source] = 0;
      priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
      pq.push({0, source});
      while (!pq.empty()) {
        auto [d, u] = pq.top();
        pq.pop();
        if (d > dist[u]) {
          continue;
        }
        for (size_t i = 0; i < G[u].size(); ++i) {
          auto [v, flow, capacity, cost, reverse] = G[u][i];
          if (capacity - flow > 0 && dist[v] > dist[u] + cost) {
            dist[v] = dist[u] + cost;
            prev[v] = u;
            prev_edge[v] = i;
            pq.push({dist[v], v});
          }
        }
      }
      if (dist[sink] == INF) {
        break;
      }
      int f = flow - total_flow;
      for (int v = sink; v != source; v = prev[v]) {
        f = min(f, G[prev[v]][prev_edge[v]].capacity - G[prev[v]][prev_edge[v]].flow);
      }
      for (int v = sink; v != source; v = prev[v]) {
        auto &e = G[prev[v]][prev_edge[v]];
        e.flow += f;
        G[v][e.reverse].flow -= f;
        total_cost += f * e.cost;
      }
      total_flow += f;
    }
    return total_cost;
  }
  vector<vector<Edge>> get_graph() {
    return G;
  }
private:
  int source, sink;
  vector<vector<Edge>> G;
};

int main() {
  assert(freopen64("cc.in", "r", stdin));
  assert(freopen64("cc.out", "w", stdout));

  int N;
  cin >> N;

  int source = 2 * N, sink = 2 * N + 1;
  WeightedNetwork network(2 * N + 2, source, sink);
  for (int i = 0; i < N; i++) {
    network.add_edge(source, i, 1, 0);
    network.add_edge(i + N, sink, 1, 0);
  }
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      int cost;
      cin >> cost;
      network.add_edge(i, j + N, 1, cost);
    }
  }

  cout << network.min_cost_flow() << '\n';

  return 0;
}