题目链接:http://acm.csu.edu.cn/csuoj/problemset/problem?pid=2082
Description
The environment of Beijing is insufferable as you know.You have to wear a mask when you go outside because of the smog. Xiaoming is new here,he has to get accustomed to the lifestyle of beijing.So at the first day he arrived there,he decide to go around to see what the whole city like.He choose n destination.But you know,the road in beijing is complex,so a thought come into xiaoming's mind :why not use "MST" algorithm to link all destination?So after a few minute,xiaoming get a map with n destination and n-1 road between them. We can define Path(u,v) as the path in the tree that doesn't pass a node twice between node u and v.What's more,if we define E(u,v) is the set of edge that appear in Path(u,v),the distance between node u and v,we can define it as D(u,v), will be equal to the sum of exclusive-or of these edge. Xiaoming want to know ∑nu=1∑nv=u+1D(u,v)
,can you help him?
Input
Input begins with a line with one integer T (1 ≤ T ≤ 5) denoting the number of test cases. Each test case begins with a line a integers n, where n (1 ≤ n ≤ 100000) denotes the number of destination. Next follow n-1 lines with three space-separated integers u, v, and w, which means there exists a edge between node u and v,and the weight of it is w(w < 2^31)
Output
For each test case, print a single line containing the answer.
Sample Input
2 4 1 2 1 2 3 1 2 4 2 4 1 2 3 2 3 1 2 4 2
Sample Output
10 12
题意: 给定一棵树(N<1e5),树边上有边权,现在求任意点对的路径异或值的和。
题解: 因为两点之间的异或Xor(u,v)=Xor(root,u)^Xor(root,v)。所以我们DFS得到每个点到根的异或值Xi。然后计算两两异或值。因为异或没有结合性,所以不能用前缀和来计算。正确的打开方式是对每一位sig,我们计算1的个数(cnt)和0的个数(N-cnt),那么这一位的贡献就是cnt*(N-cnt)*(1<<sig)。然后累计即可。
代码:
#include <stdio.h>
#include <algorithm>
#include <vector>
#include <stdlib.h>
#include <string.h>
#include <set>
#include <iostream>
using namespace std;
const int maxn = 1e5 + 7;
typedef long long ll;
vector<pair<int,int> > g[maxn];
int d[maxn];
void dfs(int u, int fa, int sta)
{
d[u] = sta;
for(int i = 0;i < g[u].size();i ++) {
pair<int,int> it = g[u][i];
if(it.first != fa) {
dfs(it.first, u, sta ^ it.second);
}
}
}
int main()
{
int T;
scanf("%d", &T);
while(T --) {
int n;
scanf("%d", &n);
for(int i = 1;i <= n;i ++) {
g[i].clear();
d[i] = 0;
}
for(int i = 1;i < n;i ++) {
int u, v, w;
scanf("%d %d %d",&u, &v, &w);
g[u].push_back(make_pair(v, w));
g[v].push_back(make_pair(u, w));
}
dfs(1, 0, 0);
ll res = 0;
for(int j = 0;j < 31;j ++) {
int bit0 = 0, bit1 = 0;
for(int i = 1;i <= n;i ++) {
if( (d[i] >> j) & 1 ) {
bit1 ++;
} else {
bit0 ++;
}
}
res += (1LL << j) * bit1 * 1LL * bit0;
}
printf("%lld\n", res);
}
return 0;
}