Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <algorithm>
- #include <iostream>
- #include <numeric>
- #include <string>
- #include <unordered_map>
- #include <utility>
- #include <vector>
- class Graph {
- public:
- Graph() = default;
- void addEdge(size_t first_vertex, size_t second_vertex) {
- if (first_vertex == edges_.size()) {
- edges_.emplace_back();
- edges_.back().push_back(second_vertex);
- } else {
- edges_[first_vertex].push_back(second_vertex);
- }
- }
- bool TryKuhn(int vertex) {
- if (used_[vertex]) {
- return false;
- }
- used_[vertex] = true;
- for (auto other_vertex : edges_[vertex]) {
- if (mt_[other_vertex] == -1 || TryKuhn(mt_[other_vertex])) {
- mt_[other_vertex] = vertex;
- return true;
- }
- }
- return false;
- }
- std::vector<int> Kuhn() {
- mt_.assign(second_size_, -1);
- std::vector<bool> global_used(first_size_);
- for (int vertex = 0; vertex < first_size_; ++vertex) {
- for (auto other_vertex : edges_[vertex]) {
- if (mt_[other_vertex] == -1) {
- mt_[other_vertex] = vertex;
- global_used[vertex] = true;
- break;
- }
- }
- }
- for (int vertex = 0; vertex < first_size_; ++vertex) {
- if (global_used[vertex]) {
- continue;
- }
- used_.assign(first_size_, false);
- TryKuhn(vertex);
- }
- std::vector<int> lines;
- for (int index = 0; index < second_size_; ++index) {
- if (mt_[index] != -1) {
- lines.push_back(index + 1);
- }
- }
- return lines;
- }
- void Reset(int first_size, int second_size) {
- first_size_ = first_size;
- second_size_ = second_size;
- }
- private:
- std::vector<std::vector<int>> edges_;
- std::vector<int> used_;
- std::vector<int> mt_;
- int first_size_;
- int second_size_;
- };
- namespace std {
- template<>
- struct hash<std::pair<int, int>> {
- inline size_t operator()(const std::pair<int, int> &v) const {
- std::hash<int> int_hasher;
- return int_hasher(v.first) ^ int_hasher(v.second);
- }
- };
- }// namespace std
- std::pair<int, int> NormalizePair(int first, int second) {
- if (first == 0) {
- return {0, 1};
- }
- auto divisor = std::gcd(first, second);
- if (first < 0) {
- divisor *= -1;
- }
- return {first / divisor, second / divisor};
- }
- int main() {
- std::ios_base::sync_with_stdio(false);
- std::cin.tie(nullptr);
- int amount_of_tests;
- std::cin >> amount_of_tests;
- for (int test_number = 0; test_number < amount_of_tests; ++test_number) {
- int lines_amount;
- std::cin >> lines_amount;
- Graph graph;
- std::unordered_map<size_t, int> indexes;
- std::unordered_map<std::pair<int, int>, size_t> first_points, second_points;
- int first_size = 0, second_size = 0;
- for (int word_number = 0; word_number < lines_amount; ++word_number) {
- int first_parameter, second_parameter, third_parameter;
- std::cin >> first_parameter >> second_parameter >> third_parameter;
- if (second_parameter == 0 && third_parameter == 0) {
- continue;
- }
- auto first_pair = NormalizePair(first_parameter, second_parameter);
- auto second_pair = NormalizePair(second_parameter, third_parameter);
- if (first_points.count(first_pair) == 0) {
- ++first_size;
- first_points.emplace(first_pair, first_points.size());
- }
- if (second_points.count(second_pair) == 0) {
- ++second_size;
- indexes[second_size] = word_number;
- second_points.emplace(second_pair, second_points.size());
- }
- graph.addEdge(first_points[first_pair], second_points[second_pair]);
- }
- if (first_size == 0) {
- std::cout << 1 << "\n" << 1 << "\n";
- continue;
- }
- graph.Reset(first_size, second_size);
- auto lines = graph.Kuhn();
- std::cout << lines.size() << "\n";
- for (auto line : lines) {
- std::cout << indexes[line] + 1 << " ";
- }
- std::cout << "\n";
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment