Cod sursa(job #2907031)

Utilizator preda.andreiPreda Andrei preda.andrei Data 28 mai 2022 15:24:00
Problema Cuplaj maxim in graf bipartit Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.96 kb
#include <fstream>
#include <iostream>
#include <optional>
#include <queue>
#include <vector>

using namespace std;

struct Bigraph {
  vector<vector<int>> cap;
  vector<vector<int>> edges;
  int nodes_a;
  int nodes_b;

  Bigraph(int nodes_a, int nodes_b) : nodes_a(nodes_a), nodes_b(nodes_b) {
    auto nodes = 2 + nodes_a + nodes_b;
    cap.resize(nodes, vector<int>(nodes, 0));
    edges.resize(nodes);

    for (auto i = 0; i < nodes_a; i += 1) {
      cap[Source()][IndexA(i)] = 1;
      edges[Source()].push_back(IndexA(i));
      edges[IndexA(i)].push_back(Source());
    }
    for (auto i = 0; i < nodes_b; i += 1) {
      cap[IndexB(i)][Dest()] = 1;
      edges[IndexB(i)].push_back(Dest());
      edges[Dest()].push_back(IndexB(i));
    }
  }

  void Tie(int node_a, int node_b) {
    auto a = IndexA(node_a);
    auto b = IndexB(node_b);
    cap[a][b] = 1;
    edges[a].push_back(b);
    edges[b].push_back(a);
  }

  int Flow(int node_a, int node_b) const {
    return cap[IndexB(node_b)][IndexA(node_a)];
  }

  int IndexA(int node_a) const {
    return node_a + 2;
  }

  int IndexB(int node_b) const {
    return node_b + nodes_a + 2;
  }

  int Size() const {
    return cap.size();
  }

  int Source() const {
    return 0;
  }

  int Dest() const {
    return 1;
  }

  const vector<int> operator[](int index) const {
    return edges[index];
  }
};

optional<vector<pair<int, int>>> FindPath(const Bigraph& graph) {
  vector<int> pre(graph.Size(), -1);
  pre[graph.Source()] = -2;

  queue<int> q;
  q.push(graph.Source());

  while (!q.empty()) {
    auto node = q.front();
    q.pop();

    for (const auto& next : graph[node]) {
      if (pre[next] == -1 && graph.cap[node][next] > 0) {
        pre[next] = node;
        q.push(next);
      }
    }
  }
  if (pre[graph.Dest()] < 0) {
    return {};
  }

  vector<pair<int, int>> path;
  for (auto node = graph.Dest(); pre[node] >= 0; node = pre[node]) {
    path.push_back({pre[node], node});
  }
  return path;
}

void Flow(Bigraph& graph, const vector<pair<int, int>>& path) {
  auto flow = 1 << 30;
  for (const auto& [a, b] : path) {
    flow = min(flow, graph.cap[a][b]);
  }
  for (const auto& [a, b] : path) {
    graph.cap[a][b] -= flow;
    graph.cap[b][a] += flow;
  }
}

vector<pair<int, int>> Solve(Bigraph& graph) {
  while (auto path = FindPath(graph)) {
    Flow(graph, *path);
  }

  vector<pair<int, int>> res;
  for (auto a = 0; a < graph.nodes_a; a += 1) {
    for (auto b = 0; b < graph.nodes_b; b += 1) {
      if (graph.Flow(a, b)) {
        res.push_back({a, b});
      }
    }
  }
  return res;
}

int main() {
  ifstream fin("cuplaj.in");
  ofstream fout("cuplaj.out");

  int nodes_a, nodes_b, edges;
  fin >> nodes_a >> nodes_b >> edges;

  Bigraph graph(nodes_a, nodes_b);
  for (auto i = 0; i < edges; i += 1) {
    int a, b;
    fin >> a >> b;
    graph.Tie(a - 1, b - 1);
  }

  auto res = Solve(graph);
  fout << res.size() << "\n";
  for (const auto& [a, b] : res) {
    fout << a + 1 << " " << b + 1 << "\n";
  }
  return 0;
}