Pagini recente » Cod sursa (job #1572904) | Cod sursa (job #2008433) | Cod sursa (job #2753296) | Cod sursa (job #3132357) | Cod sursa (job #3121852)
// https://www.infoarena.ro/problema/cuplaj
#include <fstream>
#include <vector>
#include <array>
#include <list>
#include <algorithm>
std::ifstream in("cuplaj.in");
std::ofstream out("cuplaj.out");
struct Node {
struct Edge {
Node* from;
Node* to;
bool matched = false;
Edge(Node* from, Node* to): from(from), to(to) {}
};
Node() = default;
Node(const int id, const bool main): id(id), main(main) {}
int id;
bool main;
std::vector<Edge> edges = std::vector<Edge>();
Edge* matched = nullptr;
};
struct EdgeRef {
Node::Edge* edge;
EdgeRef* back_ref;
EdgeRef(Node::Edge* edge, EdgeRef* back_ref)
: edge(std::move(edge))
, back_ref(std::move(back_ref)) {}
};
void bfs(Node& start_node) {
if (start_node.matched) {
return;
}
std::list<EdgeRef> res;
std::transform(start_node.edges.begin(), start_node.edges.end(), std::inserter(res, res.end()), [](auto& edge) -> EdgeRef {
return {&edge, nullptr};
});
auto it = res.begin();
bool finished = false;
while (it != res.end()) {
// std::cout << "checking edge " << it->edge->from->id << ' ' << it->edge->to->id << '\n';
if (it->edge->to->matched == nullptr) {
finished = true;
// std::cout << "finished\n";
break;
}
for (auto& edge: it->edge->to->edges) {
if (edge.matched != it->edge->matched) {
res.emplace_back(&edge, &(*it));
}
}
++it;
}
if (finished) {
auto ptr = &(*it);
while (ptr != nullptr) {
// std::cout << "operating edge " << ptr->edge->from->id << ' ' << ptr->edge->to->id << '\n';
ptr->edge->matched = !ptr->edge->matched;
// std::cout << "invert edge " << ptr->edge->from->id << ' ' << ptr->edge->to->id << " to " << ptr->edge->matched << '\n';
const auto pos = std::find_if(ptr->edge->to->edges.begin(), ptr->edge->to->edges.end(), [&ptr](const auto& edge) {
return edge.to == ptr->edge->from;
});
pos->matched = ptr->edge->matched;
if (ptr->edge->matched) {
ptr->edge->from->matched = ptr->edge;
// std::cout << "node " << ptr->edge->from->id << " pointed to node " << ptr->edge->to->id << '\n';
ptr->edge->to->matched = &(*pos);
// std::cout << "node " << ptr->edge->to->id << " pointed to node " << pos->to->id << '\n';
} else {
ptr->edge->from->matched = nullptr;
}
ptr = ptr->back_ref;
}
}
}
// void print_status(const std::vector<Node>& nodes) {
// for (const auto& node: nodes) {
// std::cout << node.id << ' ';
// if (node.matched == nullptr) {
// std::cout << "null";
// } else {
// std::cout << node.matched->to->id;
// }
// std::cout << '\n';
// }
// }
int main() {
int n, m, e;
in >> n >> m >> e;
std::vector<Node> nodes_a(n), nodes_b(m);
for (int i = 1; i <= n; ++i) {
nodes_a[i-1] = Node(i, true);
}
for (int i = 1; i <= m; ++i) {
nodes_b[i-1] = Node(i, false);
}
int a, b;
for (int i = 0; i < e; ++i) {
in >> a >> b;
nodes_a[a-1].edges.emplace_back(&nodes_a[a-1], &nodes_b[b-1]);
nodes_b[b-1].edges.emplace_back(&nodes_b[b-1], &nodes_a[a-1]);
}
int count = 0;
for (auto& node: nodes_a) {
// std::cout << "run for node " << node.id << '\n';
bfs(node);
// print_status(nodes_a);
if (node.matched != nullptr) {
++count;
}
}
out << count << '\n';
for (const auto& node: nodes_a) {
if (node.matched != nullptr) {
out << node.id << ' ' << node.matched->to->id << '\n';
}
}
}