Showing posts with label Centroid Decomposition. Show all posts
Showing posts with label Centroid Decomposition. Show all posts

Saturday, December 23, 2023

[Hackerearth] EvenOddity

 

Problem Link    : EvenOddity
Category        : Data Structure, Counting, Bits, Centroid Decomposition
Contest         : December Circuits'23  
Tutorial        : Counting Subarrays 
#include "bits/stdc++.h"
using namespace std;
#define int     long long int
#define endl    '\n'
 
const int maxn = 1e6 + 5;
 
struct Node {
    int v, w;
    Node(int v = 0, int w = 0)
        : v(v), w(w) {}
};
 
int n;
vector<vector<Node>> graph;
vector<int> subtree;
vector<bool> isCentroid;
int curTreeNodes;
 
void calcSubtreeSize(int u, int p) {
    subtree[u] = 1;
    for (Node it : graph[u]) {
        int v = it.v;
        if (v == p or isCentroid[v]) {
            continue;
        }
        calcSubtreeSize(v, u);
        subtree[u] += subtree[v];
    }
}
 
int getCentroid(int u, int p) {
    for (Node it : graph[u]) {
        int v = it.v;
        if (v == p or isCentroid[v]) {
            continue;
        }
        if (subtree[v] > curTreeNodes / 2) {
            return getCentroid(v, u);
        }
    }
    return u;
}
 
int cache[2][2]; // cache[ distance % 2 ][ parity(xorSum) % 2 ]
int curCache[2][2];
int ans;
 
void add(int u, int p, int lvl, int xorSum) {
    int bit = lvl & 1;
    int parity = __builtin_popcount(xorSum) & 1;
    int curAns = cache[bit ^ 1][parity];
    ans += curAns;
    curCache[bit][parity]++;
    for (Node it : graph[u]) {
        int v = it.v;
        int w = it.w;
        if (v == p or isCentroid[v]) {
            continue;
        }
        add(v, u, lvl + 1, xorSum ^ w);
    }
}
 
void decompose(int u) {
    calcSubtreeSize(u, 0);
    curTreeNodes = subtree[u];
    int centroid = getCentroid(u, 0);
    isCentroid[centroid] = true;
    memset(cache, 0, sizeof cache);
    cache[0][0] = 1;
    for (Node it : graph[centroid]) {
        int child = it.v;
        if (isCentroid[child]) {
            continue;
        }
        memset(curCache, 0, sizeof curCache);
        add(child, centroid, 1, it.w);
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                cache[i][j] += curCache[i][j];
            }
        }
    }
    for (Node it : graph[centroid]) {
        int child = it.v;
        if (isCentroid[child]) {
            continue;
        }
        decompose(child);
    }
}
 
signed main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr); cout.tie(nullptr);
    cout.precision(12);
 
    bool FILEIO = 1;
    if (FILEIO and fopen("f2.txt", "r")) {
        freopen("f2.txt", "r", stdin);
        freopen("f2out.txt", "w", stdout);
    }
 
    int tc;
    cin >> tc;
    for (int tcase = 1; tcase <= tc; tcase++) {
        cin >> n;
        graph.clear(); graph.resize(n + 1);
        subtree.clear(); subtree.resize(n + 1);
        isCentroid.clear(); isCentroid.resize(n + 1);
        for (int e = 1; e < n; e++) {
            int u, v, w;
            cin >> u >> v >> w;
            graph[u].emplace_back(v, w);
            graph[v].emplace_back(u, w);
        }
        ans = 0;
        decompose(1);
        cout << ans * 2 << endl;
    }
}

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. }