Cod sursa(job #3263480)

Utilizator the@EyE@Postavaru Stefan the@EyE@ Data 14 decembrie 2024 14:23:55
Problema Cuplaj maxim in graf bipartit Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.78 kb
#include <fstream>
#include <vector>

struct Node {
  Node(const int index, const bool is_right) {
    this->index = index;
    this->is_right = is_right;
  }

  bool IsConnected() {
    return connection != nullptr;
  }

  std::vector<Node*> neighbors;
  bool locked = false;
  Node* connection = nullptr;
  int index;
  bool is_right;
};

class Graph {
 public:
  Graph(const int num_left, const int num_right) {
    for (int index = 1; index <= num_left; ++index) {
      left_nodes.emplace_back(/*index=*/index, /*is_right=*/false);
    }
    for (int index = 1; index <= num_right; ++index) {
      right_nodes.emplace_back(/*index=*/index, /*is_right=*/true);
    }
  }

  void AddEdge(const int index_left, const int index_right) {
    left_nodes[index_left - 1].neighbors.push_back(
      &right_nodes[index_right - 1]);
    right_nodes[index_right- 1].neighbors.push_back(
      &left_nodes[index_left - 1]);
  }

  int MaximumMatch() {
    int solution = 0;
    bool was_changed = true;
    while (was_changed) {
      Unlock();
      was_changed = false;

      for (Node& node : left_nodes) {
        if (node.locked || node.IsConnected()) {
          continue;
        }

        bool success = DFS(node);
        solution += success;
        was_changed = was_changed || success;
      }
    }
    return solution;
  }

  std::vector<Node> left_nodes;
  std::vector<Node> right_nodes;

 private:
  void Unlock() {
    for (Node& node : left_nodes) {
      node.locked = false;
    }
    for (Node& node : right_nodes) {
      node.locked = false;
    }
  }

  bool DFS(Node& node) {
    if (node.locked) {
      return false;
    }

    node.locked = true;

    if (node.is_right) {
      if (!node.IsConnected()) {
        return true;
      }

      return DFS(*node.connection);
    }
    
    for (Node* neighbor : node.neighbors) {
      if (neighbor == node.connection) {
        continue;
      } 
      if (DFS(*neighbor)) {
        node.connection = neighbor;
        neighbor->connection = &node;
        return true;
      }
    }

    return false;
  }

};

int main() {
  std::ifstream in_file("cuplaj.in");
  std::ofstream out_file("cuplaj.out");

  int num_left, num_right, num_edges;
  in_file >> num_left >> num_right >> num_edges;

  Graph graph(num_left, num_right);

  for (int edge_index = 0; edge_index < num_edges; ++edge_index) {
    int index_left, index_right;
    in_file >> index_left >> index_right;
    graph.AddEdge(index_left, index_right);
  }

  out_file << graph.MaximumMatch() << '\n';

  for (const Node& node : graph.left_nodes) {
    if (node.connection != nullptr) {
      out_file << node.index << ' ' << node.connection->index << '\n';
    }
  }

  return 0;
}