Задано
дерево с n вершинами. Ребра дерева
имеют вес только 0 или 1. Найдем XOR сумму между всеми парами вершин. Вычислите
сумму всех XOR сумм.
Вход. Первая строка содержит количество вершин в графе n (2 ≤ n ≤ 105). Следующие n – 1 строк описывают ребра. Каждая строка содержит три
целых числа: номера вершин, соединенных ребром (вершины пронумерованы числами
от 1 до n), и вес ребра
(0 или 1).
Выход. Выведите
сумму XOR сумм между всеми парами вершин.
Пример
входа |
Пример
выхода |
5 1 2 1 2 3 1 2 4 0 4 5 1 |
6 |
графы –
поиск в глубину
Анализ алгоритма
При помощи поиска в
глубину вычислим XOR сумму между вершиной 1 и всеми остальными вершинами.
XOR сумму между вершинами 1 и v
занесем в x[v]. Пусть ones – количество единиц, а zeroes – количество нулей в массиве x (ones
+ zeroes = n). Тогда ответом на задачу будет число ones * zeroes.
Пример
Рассмотрим граф,
приведенный в примере.
Возле
каждой вершины v
записана XOR сумма x[v] между
1 и v. Если x[v] = x[u] для некоторых вершин v и u, то XOR сумма
между ними равна 0, таким образом совершая вклад 0 в общую сумму. XOR сумма для
каждой пары вершин (v, u), для которой x[v] ≠ x[u], дает вклад 1 в общую сумму.
Следовательно
ответ равен количеству пар вершин (v, u), для которых x[v] ≠ x[u]. Это число равно ones * zeroes = 2 * 3 = 6. Парами вершин, дающими 1 в общую
сумму, будут: (1, 2), (1, 4) , (2, 3),
(2, 5) , (3, 4) , (4, 5).
Реализация алгоритма
Входной граф храним в
списке смежности g. Объявим массив x.
vector<vector<pair<int,int> > > g;
vector<int> x;
Функция dfs реализует поиск в глубину, который вычисляет XOR
сумму x[v] между вершинами 1 и v. Текущая XOR сумма между 1 и v равна cur_xor. Предком вершины v
является p.
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[v].push_back({u,
d});
}
Запускаем поиск в глубину из вершины 1.
dfs(1, 0, -1);
Вычисляем количество нулей zeroes и единиц ones в массиве x.
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
сумму x[v] между вершинами 1 и v. Текущая XOR сумма между 1 и v равна cur_xor. Предком вершины v
является p.
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.
x = [0] * (n + 1)
Запускаем поиск в
глубину из вершины 1.
dfs(1)
Вычисляем количество
нулей zeroes и единиц ones в массиве x.
ones = sum(x)
zeroes = n – ones
Выводим ответ.
print(ones * zeroes)