matbensch

NAQ22 G Solution (C++)

Feb 4th, 2023
170
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.58 KB | None | 0 0
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <set>
  5. #include <map>
  6.  
  7. using namespace std;
  8.  
  9. ///// COPIED FROM NOTES
  10. int n;
  11. vector<vector<int>> adj;
  12. vector<vector<int>> adj_t;
  13. vector<bool> vis;
  14. vector<int> comp;
  15. vector<int> order;
  16. long long mod = 1e9+7;
  17.  
  18. void visit(int u)
  19. {
  20.     vis[u] = true;
  21.     for(int v:adj[u]) if(!vis[v]) visit(v);
  22.     order.push_back(u);
  23. }
  24.  
  25. void assign(int u, int k)
  26. {
  27.     comp[u] = k;
  28.     for(int v:adj_t[u]) if(comp[v]==-1) assign(v, k);
  29. }
  30.  
  31. void scc()
  32. {
  33.     adj_t.resize(n);
  34.     for(int u=0;u<n;u++) for(int v:adj[u]) adj_t[v].push_back(u);
  35.  
  36.     vis.resize(n);
  37.     for(int u=0;u<n;u++) if(!vis[u]) visit(u);
  38.     reverse(order.begin(), order.end());
  39.  
  40.     comp.assign(n, -1);
  41.     int curr = 0;
  42.     for(int u:order) if(comp[u]==-1) assign(u, curr++);
  43. }
  44. //////////////////////////////////////////////////////////
  45.  
  46. // calculate number of variants ending at a node c
  47. // given the transposed condensation graph
  48. long long cont(vector<set<int>>& hg_t, int c)
  49. {
  50.     if(hg_t[c].size()==0) return 1;
  51.  
  52.     long long pp = 1;
  53.     for(int p:hg_t[c])
  54.     {
  55.         pp = (pp * ( (cont(hg_t, p) + 1) % mod) % mod) % mod;
  56.     }
  57.  
  58.     // i went overkill on the mods
  59.     return pp % mod;
  60. }
  61.  
  62. int main()
  63. {
  64.     // build the initial graph
  65.     cin>>n;
  66.     adj.assign(n, vector<int>(0));
  67.     for(int u=0;u<n;u++)
  68.     {
  69.         int v;
  70.         cin>>v;
  71.         v--;
  72.         adj[u].push_back(v);
  73.     }
  74.  
  75.     // run scc
  76.     scc();
  77.  
  78.     // maps scc id to the nodes in that scc
  79.     map<int,vector<int>> ctn;
  80.     for(int i=0;i<n;i++) ctn[comp[i]].push_back(i);
  81.  
  82.     // build the condensation graph
  83.     // by checking for scc adjacency to other scc's
  84.     int n_comps = ctn.size();
  85.     vector<set<int>> hg;
  86.     hg.resize(n_comps);
  87.  
  88.     for(int c=0;c<n_comps;c++)
  89.     {
  90.         for(int u:ctn[c])
  91.             for(int v:adj[u])
  92.                 if(comp[v]!=c) hg[c].insert(comp[v]);
  93.     }
  94.  
  95.  
  96.     // find the sinks of the condensation graph
  97.     set<int> sinks;
  98.     for(int c=0;c<n_comps;c++) if(hg[c].size()==0) sinks.insert(c);
  99.  
  100.  
  101.     // build transposed condensation graph
  102.     vector<set<int>> hg_t(n_comps);
  103.     for(int c=0;c<n_comps;c++)
  104.     {
  105.         for(int k:hg[c]) hg_t[k].insert(c);
  106.     }
  107.  
  108.     // calculate answer
  109.     long long ans = 1;
  110.     for(int sink : sinks)
  111.     {
  112.         ans =  (ans * ( cont(hg_t, sink) + 1 ) % mod ) % mod; //(ans + (fast_pow(2, n_sinks-1) * cont(hg_t, sink)) % mod) % mod;
  113.     }
  114.  
  115.     // subtracting 1 to disclude empty set
  116.     ans = (mod + ans - 1) % mod;
  117.  
  118.     cout << ans << '\n';
  119. }
Advertisement
Add Comment
Please, Sign In to add comment