CRB and Tree
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2244 Accepted Submission(s): 683
Problem Description
CRB has a tree, whose vertices are labeled by 1, 2, …,
N
. They are connected by
N
– 1 edges. Each edge has a weight.
For any two vertices u and v (possibly equal), f(u,v) is xor(exclusive-or) sum of weights of all edges on the path from u to v .
CRB’s task is for given s , to calculate the number of unordered pairs (u,v) such that f(u,v) = s . Can you help him?
For any two vertices u and v (possibly equal), f(u,v) is xor(exclusive-or) sum of weights of all edges on the path from u to v .
CRB’s task is for given s , to calculate the number of unordered pairs (u,v) such that f(u,v) = s . Can you help him?
Input
There are multiple test cases. The first line of input contains an integer
T
, indicating the number of test cases. For each test case:
The first line contains an integer N denoting the number of vertices.
Each of the next N - 1 lines contains three space separated integers a , b and c denoting an edge between a and b , whose weight is c .
The next line contains an integer Q denoting the number of queries.
Each of the next Q lines contains a single integer s .
1 ≤ T ≤ 25
1 ≤ N ≤ 105
1 ≤ Q ≤ 10
1 ≤ a , b ≤ N
0 ≤ c , s ≤ 105
It is guaranteed that given edges form a tree.
The first line contains an integer N denoting the number of vertices.
Each of the next N - 1 lines contains three space separated integers a , b and c denoting an edge between a and b , whose weight is c .
The next line contains an integer Q denoting the number of queries.
Each of the next Q lines contains a single integer s .
1 ≤ T ≤ 25
1 ≤ N ≤ 105
1 ≤ Q ≤ 10
1 ≤ a , b ≤ N
0 ≤ c , s ≤ 105
It is guaranteed that given edges form a tree.
Output
For each query, output one line containing the answer.
Sample Input
1 3 1 2 1 2 3 2 3 2 3 4
Sample Output
1 1 0HintFor the first query, (2, 3) is the only pair that f(u, v) = 2. For the second query, (1, 3) is the only one. For the third query, there are no pair (u, v) such that f(u, v) = 4.
思路:它是一棵树,树的根为 1,那么 f(1,u) 表示从 根节点一直异或到u,f(1,v)表示从根节点异或到 v
那么 f(1,u) ^ f(1,v) = f(u,v) , 所以只要求出 根节点到所有其他节点的异或值就可以了 记录为 dp[i]
特殊情况是 当 s = 0 的时候 ,pair(u,u) 是满足的,所以 ans += u
然后对于一般情况,从2到n,如果 dp[i] == s,那么 ans ++ ,表示 pair(1,i) 满足
然后就是令 tmp = dp[i] ^ s ,则有 cnt[tmp]种情况是满足的 因为 tmp ^ dp[i] = s,但是这里有重复情况,要除 2
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
#define mem(a,x) memset(a,x,sizeof(a))
#define ll long long
#define maxn 100005
struct node{
int v,w;
node(int v_,int w_) : v(v_),w(w_){}
};
vector<node>vec[maxn];
int cnt[maxn * 2];
ll dp[maxn * 2],sum,ans;
void add(int u,int v,int w){
vec[u].push_back(node(v,w));
}
void treedp(int u,int pre){
int v,w;
int sz = vec[u].size();
for(int i = 0;i < sz;i++){
v = vec[u][i].v;
w = vec[u][i].w;
if(v == pre)
continue;
dp[v] = dp[u] ^ w;
cnt[dp[v]]++;
treedp(v,u);
}
}
int main(){
int t,n,q,u,v,w,s,tmp;
scanf("%d",&t);
while(t--){
mem(cnt,0);
scanf("%d",&n);
for(int i = 1;i <= n;i++)
vec[i].clear();
for(int i = 1;i < n;i++){
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dp[1] = 0;
treedp(1,-1);
scanf("%d",&q);
while(q--){
sum = ans = 0;
scanf("%d",&s);
if(s == 0)
ans += n;
for(int i = 2;i <= n;i++){
if(s == dp[i])
ans++;
tmp = dp[i] ^ s;
sum += cnt[tmp];
if(tmp == dp[i])
sum--;
}
printf("%lld\n",sum / 2 + ans);
}
}
return 0;
}