Сума XOR#10653

Сума XOR (Розбір)

За допомогою пошуку в глибину обчислимо XOR суму між вершиною і всіма іншими вершинами. XOR суму між вершинами і занесемо в . Нехай — кількість одиниць, а — кількість нулів у масиві x~(ones + zeroes = n). Тоді відповідь на задачу буде числом ones \cdot zeroes.

Приклад

Розглянемо граф, наведений у прикладі.

Біля кожної вершини записано XOR суму між і . Якщо x[v] = x[u] для деяких вершин і , то XOR сума між ними дорівнює , таким чином вносячи вклад в загальну суму. XOR сума для кожної пари вершин , для якої x[v] \ne x[u], дає вклад у загальну суму.

Отже, відповідь дорівнює кількості пар вершин , для яких x[v] \ne x[u]. Це число дорівнює ones \cdot zeroes = 2 \cdot 3 = 6. Парами вершин, що дають в загальну суму, будуть: (1, 2), (1, 4), (2, 3), (2, 5), (3, 4), (4, 5).

Реалізація алгоритму

Вхідний граф зберігаємо в списку суміжності . Оголосимо масив .

vector<vector<pair<int,int> > > g;
vector<int> x;

Функція dfs реалізує пошук в глибину, який обчислює XOR суму між вершинами і . Поточна XOR сума між і дорівнює cur\_xor. Предком вершини є .

void dfs(int v, int cur_xor, int p = -1)
{
  x[v] = cur_xor;
  for (auto z : g[v])
  {
    int to = z.first;
    int w = z.second;
    if (to != p) dfs(to, cur_xor ^ w, v);
  }
}

Основна частина програми. Читаємо вхідний граф.

scanf("%d", &n);
g.resize(n + 1);
x.resize(n + 1);

for (i = 1; i < n; i++)
{
  scanf("%d %d %d", &u, &v, &d);
  g[u].push_back({v, d});
  g[v].push_back({u, d});
}

Запускаємо пошук в глибину з вершини .

dfs(1, 0, -1);

Обчислюємо кількість нулів і одиниць у масиві .

ones = 0;
for (i = 1; i <= n; i++)
  if (x[i] == 1) ones++;
zeroes = n - ones;

Виводимо відповідь.

printf("%lld\n", 1LL * ones * zeroes);

Python реалізація

Функція dfs реалізує пошук в глибину, який обчислює XOR суму між вершинами і . Поточна XOR сума між і дорівнює cur\_xor. Предком вершини є .

def dfs(v, cur_xor = 0, p = -1):
  x[v] = cur_xor
  for to, w in g[v]:
    if to != p:
      dfs(to, cur_xor ^ w, v)

Основна частина програми. Читаємо вхідний граф.

n = int(input())
g = [[] for _ in range(n + 1)]
for _ in range(n - 1):
  u, v, d = map(int, input().split())
  g[u].append((v, d))
  g[v].append((u, d))

Ініціалізуємо масив .

x = [0] * (n + 1)

Запускаємо пошук в глибину з вершини .

dfs(1)

Обчислюємо кількість нулів і одиниць у масиві .

ones = sum(x)
zeroes = n - ones

Виводимо відповідь.

print(ones * zeroes)