Advertisement
gertsog

F

Oct 16th, 2019
420
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.81 KB | None | 0 0
  1.     #include <iostream>
  2.     #include <algorithm>
  3.     #include <vector>
  4.     #include <unordered_set>
  5.      
  6.     typedef std::vector<int> iVec;
  7.     typedef std::unordered_multiset<int> iumSet;
  8.     typedef std::unordered_set<int> iuSet;
  9.     typedef std::vector<bool> bVec;
  10.     typedef std::vector<iumSet> matr;
  11.      
  12.     matr G, Gt;
  13.     std::vector<iuSet> Comps;
  14.     bVec used;
  15.     iVec order;
  16.      
  17.     void topsort( int v )
  18.     {
  19.       used[v] = true;
  20.       for (auto i : G[v])
  21.         if (!used[i])
  22.           topsort(i);
  23.       order.push_back(v);
  24.     }
  25.      
  26.     void dfs( int v, int cur_comp )
  27.     {
  28.       used[v] = true;
  29.       Comps[cur_comp].insert(v);
  30.       for (auto i : Gt[v])
  31.         if (!used[i])
  32.           dfs(i, cur_comp);
  33.     }
  34.      
  35.     int main()
  36.     {
  37.       int n = 0, m = 0, i = 0, j = 0;
  38.      
  39.       // Obtain G and Gt (transposed)
  40.       scanf("%i%i", &n, &m);
  41.       G.resize(n);
  42.       Gt.resize(n);
  43.       used.resize(n);
  44.       while (m--)
  45.       {
  46.         scanf("%i%i", &i, &j);
  47.         G[--i].insert(--j);
  48.         Gt[j].insert(i);
  49.       }
  50.      
  51.       // Sort G
  52.       std::generate(used.begin(), used.end(), []() { return false; });
  53.       for (i = 0; i < n; ++i)
  54.         if (!used[i])
  55.           topsort(i);
  56.      
  57.       int cnt = 0;
  58.      
  59.       // Collect comps in Gt
  60.       std::generate(used.begin(), used.end(), []() { return false; });
  61.       for (i = 0; i < n; ++i)
  62.       {
  63.         int v = order[n - 1 - i];
  64.         Comps.push_back(iuSet());
  65.         if (!used[v])
  66.           dfs(v, cnt++);
  67.       }
  68.      
  69.       cnt = 0;
  70.      
  71.       // Count edges
  72.       used.resize(Comps.size());
  73.       std::generate(used.begin(), used.end(), []() { return false; });
  74.       for (i = 0; i < Comps.size(); i++)
  75.         for (j = 0; j < Comps.size(); j++)
  76.         {
  77.           if (i == j)
  78.             continue;
  79.      
  80.           // check edges btw comps
  81.           for (auto a : Comps[i])
  82.           {
  83.             if (used[i] && used[j]) // to skip duplicating edges
  84.               break;
  85.      
  86.             for (auto b : Comps[j])
  87.             {
  88.               bool
  89.                 res1 = std::find(G[a].begin(), G[a].end(), b) != G[a].end(),
  90.                 res2 = std::find(G[b].begin(), G[b].end(), a) != G[b].end();
  91.      
  92.               if (res1 || res2)
  93.               {
  94.                 used[i] = used[j] = true;
  95.                 if (res1 && res2)
  96.                 {
  97.                   // merge comps, vstrechnye rebra
  98.                   Comps[i].insert(Comps[j].begin(), Comps[j].end());
  99.                   Comps.erase(Comps.begin() + j);
  100.                   used.erase(used.begin() + j--);
  101.                 }
  102.                 else
  103.                   cnt++;
  104.                 break;
  105.               }
  106.             }
  107.           }
  108.         }
  109.      
  110.       std::cout << cnt;
  111.      
  112.       return 0;
  113.     }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement