Cod sursa(job #2907043)

Utilizator preda.andreiPreda Andrei preda.andrei Data 28 mai 2022 16:01:49
Problema Cuplaj maxim in graf bipartit Scor 50
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.01 kb
#include <fstream>
#include <iostream>
#include <queue>
#include <unordered_map>
#include <vector>

using namespace std;

struct Bigraph {
  vector<unordered_map<int, int>> cap;
  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);

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

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

  int Flow(int node_a, int node_b) const {
    if (!cap[IndexB(node_b)].count(IndexA(node_a))) {
      return 0;
    }
    return cap[IndexB(node_b)].at(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;
  }
};

vector<int> FindPre(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& p : graph.cap[node]) {
      auto next = p.first;
      auto cap = p.second;
      if (pre[next] == -1 && cap > 0) {
        pre[next] = node;
        q.push(next);
      }
    }
  }
  return pre;
}

void Flow(Bigraph& graph, const vector<int>& pre, int before_last) {
  auto node = graph.Dest();
  auto prev = before_last;
  auto flow = 1 << 30;
  while (prev >= 0) {
    flow = min(flow, graph.cap[prev][node]);
    node = prev;
    prev = pre[prev];
  }

  node = graph.Dest();
  prev = before_last;
  while (prev >= 0) {
    graph.cap[prev][node] -= flow;
    graph.cap[node][prev] += flow;
    node = prev;
    prev = pre[prev];
  }
}

void Flow(Bigraph& graph, const vector<int>& pre) {
  for (auto i = 0; i < graph.nodes_b; i += 1) {
    auto b = graph.IndexB(i);
    if (pre[b] >= 0) {
      Flow(graph, pre, b);
    }
  }
}

vector<pair<int, int>> Solve(Bigraph& graph) {
  auto pre = FindPre(graph);
  while (pre[graph.Dest()] >= 0) {
    Flow(graph, pre);
    pre = FindPre(graph);
  }

  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& p : res) {
    fout << p.first + 1 << " " << p.second + 1 << "\n";
  }
  return 0;
}