Advertisement
Nik_Perepelov

Авиаперелёты OK

Nov 16th, 2021 (edited)
1,031
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.34 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <set>
  4.  
  5. using namespace std;
  6.  
  7. vector<vector<int>> g, g_r;
  8. vector<bool> used;
  9. vector<int> order;
  10. vector<int> component;
  11.  
  12. void dfs(int v) {
  13.     used[v] = true;
  14.     for (int i: g[v])
  15.         if (!used[i])
  16.             dfs(i);
  17.     order.emplace_back(v);
  18. }
  19.  
  20. void dfs_r(int v) {
  21.     used[v] = true;
  22.     component.push_back(v);
  23.     for (int i: g_r[v])
  24.         if (!used[i])
  25.             dfs_r(i);
  26. }
  27.  
  28.  
  29. class Graph {
  30.     vector<set<int>> g;
  31.     vector<bool> used;
  32.  
  33. public:
  34.  
  35.     explicit Graph(int n) {
  36.         g.resize(n);
  37.         used.resize(n);
  38.     }
  39.  
  40.     void set_graph(vector<set<int>> &_g) {
  41.         g = _g;
  42.     }
  43.  
  44.     vector<set<int>> get_graph() {
  45.         return g;
  46.     }
  47.  
  48.     int dfs_to_delete_edges(int v, int finish) {
  49.         if (v == finish) {
  50.             return 1;
  51.         }
  52.         used[v] = true;
  53.         for (auto &i: g[v]) {
  54.             if (!used[i]) {
  55.                 int res = dfs_to_delete_edges(i, finish);
  56.                 if (res)
  57.                     return res + 1;
  58.             }
  59.         }
  60.         return 0;
  61.     }
  62.  
  63.     void exec() {
  64.         for (auto & i : g) {
  65.  
  66.             // дфс в котором если находим ребро от стартовой до финишной вершины, и при этом у нас есть другие пути, то удаляем это ребро
  67.             auto curr_copy = i;
  68.             for (auto &k: curr_copy) { // будем смотреть сразу прямые рёбра, мы же их знаем
  69.                 bool is_path_not_1 = false;
  70.                 used.assign(used.size(), false);
  71.                 for (auto &j: i) {
  72.                     if (!used[j]) {
  73.                         int tmp = dfs_to_delete_edges(j, k);
  74.                         if (tmp > 1) {
  75.                             is_path_not_1 = true;
  76.                             break;
  77.                         }
  78.                     }
  79.                 }
  80.                 // если нашлёлся путь длины больше 1, то удаляем это ребро
  81.                 if (is_path_not_1) {
  82.                     i.erase(i.find(k));
  83.                 }
  84.             }
  85.         }
  86.     }
  87. };
  88.  
  89. int main() {
  90.     int n, m;
  91.     cin >> n >> m;
  92.  
  93.     used = vector<bool>(n);
  94.     g = vector<vector<int>>(n);
  95.     g_r = vector<vector<int>>(n);
  96.     vector<pair<int, int>> edges(m);
  97.  
  98.     for (int i = 0; i < m; i++) {
  99.         int fr, to;
  100.         cin >> fr >> to;
  101.         fr--;
  102.         to--;
  103.         g[fr].emplace_back(to);
  104.         g_r[to].emplace_back(fr);
  105.         edges[i] = make_pair(fr, to);
  106.     }
  107.  
  108.     for (int i = 0; i < n; i++)
  109.         if (!used[i])
  110.             dfs(i);
  111.  
  112.     used = vector<bool>(n);
  113.  
  114.     vector<int> component_for_vertex(n, -1);
  115.     vector<int> any_vertex_for_component;
  116.     vector<pair<int, int>> answer;
  117.     int cnt = 0;
  118.     for (int i = 0; i < n; i++) {
  119.         int v = order[n - 1 - i];
  120.         if (!used[v]) {
  121.             dfs_r(v);
  122.             any_vertex_for_component.emplace_back(component[0]);
  123.             for (int j = 0; j < component.size() - 1; j++) {
  124.                 component_for_vertex[component[j]] = cnt;
  125.                 answer.emplace_back(component[j], component[j + 1]);
  126.             }
  127.             component_for_vertex[component[component.size() - 1]] = cnt;
  128.             if (component.size() > 1)
  129.                 answer.emplace_back(component[component.size() - 1], component[0]);
  130.             cnt++;
  131.             component.clear();
  132.         }
  133.     }
  134.  
  135.     vector<set<int>> new_g(cnt);
  136.     for (int i = 0; i < m; i++) {
  137.         if (component_for_vertex[edges[i].first] != component_for_vertex[edges[i].second]) {
  138.             // значит ребро между разными скс
  139.             new_g[component_for_vertex[edges[i].first]].insert(component_for_vertex[edges[i].second]);
  140.         }
  141.     }
  142.  
  143.     // теперь работаем с деревом из скс
  144.     Graph sks(cnt);
  145.     sks.set_graph(new_g);
  146.     sks.exec();
  147.     new_g = sks.get_graph();
  148.  
  149.     for (int i = 0; i < new_g.size(); i++) {
  150.         for (auto &j: new_g[i])
  151.             answer.emplace_back(any_vertex_for_component[i], any_vertex_for_component[j]);
  152.     }
  153.  
  154.     cout << answer.size() << '\n';
  155.     for (auto &i: answer) {
  156.         cout << i.first + 1 << ' ' << i.second + 1 << '\n';
  157.     }
  158.  
  159. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement