Cod sursa(job #2150859)

Utilizator preda.andreiPreda Andrei preda.andrei Data 3 martie 2018 20:41:19
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.98 kb
#include <fstream>
#include <vector>

using namespace std;

struct BiGraph
{
  vector<vector<int>> a;
  vector<vector<int>> b;

  BiGraph(int n, int m)
    : a(vector<vector<int>>(n)),
      b(vector<vector<int>>(m)) {}
};

struct Partners
{
  vector<int> a;
  vector<int> b;

  Partners(int n, int m)
    : a(vector<int>(n, -1)),
      b(vector<int>(m, -1)) {}

  void Couple(int node_a, int node_b)
  {
    a[node_a] = node_b;
    b[node_b] = node_a;
  }
};

using Matching = vector<pair<int, int>>;

bool Couple(const BiGraph &g, Partners &part, int node, vector<bool> &used)
{
  if (used[node]) {
    return false;
  }
  used[node] = true;

  for (const auto &next : g.a[node]) {
    if (part.b[next] == -1) {
      part.Couple(node, next);
      return true;
    }
  }

  for (const auto &next : g.a[node]) {
    auto other = part.b[next];
    if (Couple(g, part, other, used)) {
      part.Couple(node, next);
      return true;
    }
  }
  return false;
}

Matching ExtractMatching(const vector<int> &partner)
{
  Matching matching;
  for (size_t i = 0; i < partner.size(); ++i) {
    if (partner[i] != -1) {
      matching.push_back({i, partner[i]});
    }
  }
  return matching;
}

Matching FindMatching(const BiGraph &g)
{
  Partners part(g.a.size(), g.b.size());
  auto done = false;

  while (!done) {
    done = true;
    vector<bool> used(g.a.size(), false);

    for (size_t i = 0; i < g.a.size(); ++i) {
      if (part.a[i] == -1 && Couple(g, part, i, used)) {
        done = false;
      }
    }
  }
  return ExtractMatching(part.a);
}

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

  int n, m, edges;
  fin >> n >> m >> edges;

  BiGraph graph(n, m);
  for (int i = 0; i < edges; ++i) {
    int a, b;
    fin >> a >> b;
    graph.a[a - 1].push_back(b - 1);
    graph.b[b - 1].push_back(a - 1);
  }

  auto matching = FindMatching(graph);
  fout << matching.size() << "\n";

  for (const auto &p : matching) {
    fout << p.first + 1 << " " << p.second + 1 << "\n";
  }
  return 0;
}