Cod sursa(job #2062831)

Utilizator preda.andreiPreda Andrei preda.andrei Data 10 noiembrie 2017 21:18:48
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 1.92 kb
#include <fstream>
#include <vector>

using namespace std;

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

bool Couple(int node,
            vector<bool> &vis,
            vector<int> &match_l,
            vector<int> &match_r,
            const GraphPart &g)
{
  if (vis[node]) {
    return false;
  }
  vis[node] = true;

  for (const auto &other : g[node]) {
    if (match_r[other] == -1) {
      match_l[node] = other;
      match_r[other] = node;
      return true;
    }
  }

  for (const auto &other : g[node]) {
    auto other_left = match_r[other];
    if (Couple(other_left, vis, match_l, match_r, g)) {
      match_l[node] = other;
      match_r[other] = node;
      return true;
    }
  }
  return false;
}

Matching BuildMatching(const vector<int> &matches)
{
  Matching matching;
  for (size_t i = 0; i < matches.size(); ++i) {
    if (matches[i] >= 0) {
      matching.push_back({i, matches[i]});
    }
  }
  return matching;
}

Matching FindMatching(const GraphPart &l, int right_nodes)
{
  vector<int> match_l(l.size(), -1);
  vector<int> match_r(right_nodes, -1);

  bool changes = false;
  do {
    changes = false;
    vector<bool> visited(l.size(), false);

    for (size_t i = 0; i < l.size(); ++i) {
      if (match_l[i] > -1) {
        continue;
      }

      if (Couple(i, visited, match_l, match_r, l)) {
        changes = true;
      }
    }
  } while (changes);

  return BuildMatching(match_l);
}

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

  int count_left, count_right, edges;
  fin >> count_left >> count_right >> edges;

  GraphPart left(count_left);
  for (int i = 0; i < edges; ++i) {
    int x, y;
    fin >> x >> y;
    left[x - 1].push_back(y - 1);
  }

  auto matching = FindMatching(left, count_right);
  fout << matching.size() << "\n";

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