Tuesday, January 22, 2019

[Codechef] Prime Distance on Tree

Author            : Dipu Kumar Mohanto 
                    CSE, Batch - 6
                    BRUR.
Problem Statement : Prime Distance on Tree
Source            : Codechef
Category          : Graph Theory
Algorithm         : Centroid Decomposition
Verdict           : Accepted

  1. #include "bits/stdc++.h"  
  2.   
  3. using namespace std;  
  4.   
  5. #define ll          long long int  
  6.   
  7. static const int maxn = 1e5 + 5;  
  8. static const int logn = 18;  
  9.   
  10. vector <int> graph[maxn];  
  11. int subtreeSize[maxn];  
  12. bool is_centroid[maxn];  
  13. int num;  
  14.   
  15. ll ndist[logn][maxn];  
  16.   
  17. bool isPrime[maxn];  
  18. vector <int> prime;  
  19.   
  20. inline void seive()  
  21. {  
  22.       for (int i = 0; i < maxn; i++) isPrime[i] = 1;  
  23.       isPrime[0] = isPrime[1] = 0;  
  24.       for (int i = 4; i < maxn; i += 2) isPrime[i] = 0;  
  25.       for (int i = 3; i * i <= maxn; i += 2)  
  26.       {  
  27.             if (isPrime[i])  
  28.             {  
  29.                   for (int j = i*i; j < maxn; j += i+i) isPrime[j] = 0;  
  30.             }  
  31.       }  
  32.       prime.emplace_back(2);  
  33.       for (int i = 3; i < maxn; i += 2) if (isPrime[i]) prime.emplace_back(i);  
  34. }  
  35.   
  36. inline void dfs(int u, int p = -1)  
  37. {  
  38.       subtreeSize[u] = 1;  
  39.       for (int v : graph[u])  
  40.       {  
  41.             if (v == p or is_centroid[v]) continue;  
  42.             dfs(v, u);  
  43.             subtreeSize[u] += subtreeSize[v];  
  44.       }  
  45. }  
  46.   
  47. inline int get_centroid(int u, int p = -1)  
  48. {  
  49.       for (int v : graph[u])  
  50.       {  
  51.             if (v == p or is_centroid[v]) continue;  
  52.             if (subtreeSize[v] > (num/2)) return get_centroid(v, u);  
  53.       }  
  54.       return u;  
  55. }  
  56.   
  57. inline void Add(int u, int p, int depth, int dist, int add)  
  58. {  
  59.       ndist[depth][dist] += add;  
  60.       for (int v : graph[u])  
  61.       {  
  62.             if (v == p or is_centroid[v]) continue;  
  63.             Add(v, u, depth, dist+1, add);  
  64.       }  
  65. }  
  66.   
  67. inline ll calcPrimeDistance(int u, int p, int depth, int dist)  
  68. {  
  69.       ll ret = 0;  
  70.       for (int p : prime)  
  71.       {  
  72.             if (p < dist) continue;  
  73.             if (ndist[depth][p-dist] == 0) break;  
  74.             if (p != dist) ret += ndist[depth][p-dist];  
  75.             else ret += 2*ndist[depth][p-dist];  
  76.       }  
  77.       for (int v : graph[u])  
  78.       {  
  79.             if (v == p or is_centroid[v]) continue;  
  80.             ret += calcPrimeDistance(v, u, depth, dist+1);  
  81.       }  
  82.       return ret;  
  83. }  
  84.   
  85. ll ans;  
  86.   
  87. inline void decompose(int u, int depth)  
  88. {  
  89.       dfs(u, -1);  
  90.       num = subtreeSize[u];  
  91.       int centroid = get_centroid(u);  
  92.       is_centroid[centroid] = 1;  
  93.       Add(centroid, -1, depth, 0, 1);  
  94.       ll ret = 0;  
  95.       for (int v : graph[centroid])  
  96.       {  
  97.             if (is_centroid[v]) continue;  
  98.             Add(v, centroid, depth, 1, -1);  
  99.             ret += calcPrimeDistance(v, centroid, depth, 1);  
  100.             Add(v, centroid, depth, 1, 1);  
  101.       }  
  102.       ans += ret / 2;  
  103.       for (int v : graph[centroid])  
  104.       {  
  105.             if (is_centroid[v]) continue;  
  106.             decompose(v, depth+1);  
  107.       }  
  108.       for (int i = 0; i < maxn && ndist[depth][i]; i++) ndist[depth][i] = 0;  
  109. }  
  110.   
  111. int main()  
  112. {  
  113.       seive();  
  114.       int tnode;  
  115.       cin >> tnode;  
  116.       for (int e = 1; e < tnode; e++)  
  117.       {  
  118.             int u, v;  
  119.             cin >> u >> v;  
  120.             graph[u].emplace_back(v);  
  121.             graph[v].emplace_back(u);  
  122.       }  
  123.       decompose(1, 0);  
  124.       ll nCr = (ll)tnode * (ll)(tnode-1) / 2;  
  125.       double pro = (double)ans / (double)nCr;  
  126.       cout << fixed << setprecision(6) << pro << endl;  
  127. }  

No comments:

Post a Comment

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