Saturday, February 9, 2019

[CodeChef] GRAPHCNT - Counting on a directed graph

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : GRAPHCNT - Counting on a directed graph
Source            : CodeChef
Category          : Graph Theory
Algorithm         : Dominator Tree
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. #define vi        vector <int>  
  6. #define eb        emplace_back  
  7. #define sz(v)     (int)v.size()  
  8. #define ll        long long int  
  9.   
  10. static const int maxn = 2e5 + 5;  
  11.   
  12. vi graph[maxn],    // Input Graph.  
  13.    rgraph[maxn],   // Reverse Graph.  
  14.    Tree[maxn],     // Final Dominator Tree.  
  15.    bucket[maxn];   // For a vertex i, it stores a list of vertices for which i is the  
  16.                    // semi-dominator. Initially it is empty.  
  17.   
  18. int arr[maxn],     // Mapping of i'th node to its new index, equal to the arrival time  
  19.                    // of node in dfs tree.  
  20.     par[maxn],     // Parent of node i in dfs tree.  
  21.     rev[maxn],     // Reverse mapping of i'th node to the original label in input graph.  
  22.     sdom[maxn],    // Label of semi-dominator of i'th node. Initially sdom[i] = i.  
  23.     dom[maxn],     // Label of immediate-dominator of the i'th node. Initially dom[i] = i.  
  24.     dsu[maxn],     // Parent of i'th node in the forest maintained during step 2 of the  
  25.                    // algorithm. Initially dsu[i] = i.  
  26.     label[maxn],   // At any point of time, label[i] stores the vertex v with minimum sdom,  
  27.                    // lying on path from i to the root of the (dsu) tree in which node i  
  28.                    // lies. Initially, label[i] = i.  
  29.     dfsTime;  
  30.   
  31. // 1 - Based directed graph input.  
  32.   
  33. int Find(int u, int x = 0)  
  34. {  
  35.       if (u == dsu[u]) return x ? -1 : u;  
  36.       int v = Find(dsu[u], x+1);  
  37.       if (v < 0) return u;  
  38.       if (sdom[ label[ dsu[u] ] ] < sdom[ label[u] ])  
  39.       {  
  40.             label[u] = label[ dsu[u] ];  
  41.       }  
  42.       dsu[u] = v;  
  43.       return x ? v : label[u];  
  44. }  
  45.   
  46. void Union(int u, int v)  // Add an edge to u -> v  
  47. {  
  48.       dsu[v] = u;  
  49. }  
  50.   
  51. void dfs(int u)  
  52. {  
  53.       ++dfsTime;  
  54.       arr[u] = dfsTime;  
  55.       rev[dfsTime] = u;  
  56.       label[dfsTime] = dfsTime;  
  57.       sdom[dfsTime] = dfsTime;  
  58.       dsu[dfsTime] = dfsTime;  
  59.       for (int v : graph[u])  
  60.       {  
  61.             if (!arr[v])  
  62.             {  
  63.                   dfs(v);  
  64.                   par[ arr[v] ] = arr[u];  
  65.             }  
  66.             rgraph[ arr[v] ].eb(arr[u]);  
  67.       }  
  68. }  
  69.   
  70. void DominatorTree(int src)  
  71. {  
  72.       dfs(src);  
  73.       int n = dfsTime;  
  74.       for (int i = n; i >= 1; i--)  
  75.       {  
  76.             for (int j = 0; j < sz(rgraph[i]); j++)  
  77.             {  
  78.                   sdom[i] = min(sdom[i], sdom[ Find(rgraph[i][j]) ]);  
  79.             }  
  80.             if (i > 1) bucket[ sdom[i] ].eb(i);  
  81.             for (int j = 0; j < sz(bucket[i]); j++)  
  82.             {  
  83.                   int w = bucket[i][j];  
  84.                   int v = Find(w);  
  85.                   if (sdom[v] == sdom[w]) dom[w] = sdom[w];  
  86.                   else dom[w] = v;  
  87.             }  
  88.             if (i > 1) Union(par[i], i);  
  89.       }  
  90.       for (int i = 2; i <= n; i++)  
  91.       {  
  92.             if (dom[i] != sdom[i]) dom[i] = dom[ dom[i] ];  
  93.             Tree[ rev[i] ].eb(rev[ dom[i] ]);  
  94.             Tree[ rev[ dom[i] ] ].eb(rev[i]);  
  95.       }  
  96. }  
  97.   
  98. int subtreeSize[maxn];  
  99.   
  100. void dfs1(int u, int p = -1)  
  101. {  
  102.       subtreeSize[u] = 1;  
  103.       for (int v : Tree[u])  
  104.       {  
  105.             if (v == p) continue;    
  106.             dfs1(v, u);  
  107.             subtreeSize[u] += subtreeSize[v];  
  108.       }  
  109. }  
  110.   
  111. int main()  
  112. {  
  113.       ///freopen("in.txt", "r", stdin);  
  114.       int tnode, tedge;  
  115.       cin >> tnode >> tedge;  
  116.       for (int e = 1; e <= tedge; e++)  
  117.       {  
  118.             int u, v;  
  119.             cin >> u >> v;  
  120.             graph[u].eb(v);  
  121.       }  
  122.       int src = 1;  
  123.       DominatorTree(src); // Build Dominator Tree  
  124.       dfs1(src);  
  125.       ll ans = subtreeSize[src] - 1;  
  126.       ll sum = 0;  
  127.       for (int child : Tree[src])  
  128.       {  
  129.             ans += (ll)subtreeSize[child] * sum;  
  130.             sum += subtreeSize[child];  
  131.       }  
  132.       cout << ans << endl;  
  133. }  

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.