CRB and Tree
http://acm.hdu.edu.cn/showproblem.php?pid=5416
Time Limit: 8000/4000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2411 Accepted Submission(s): 730
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?
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.
Output
For each query, output one line containing the answer.
Sample Input
1
3
1 2 1
2 3 2
5
2
3
4
0
0
Sample Output
1
1
0
Hint
For 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.
Author
KUT(DPRK)
Source
2015 Multi-University Training Contest 10
Recommend
wange2014 | We have carefully selected several similar problems for you: 6408 6407 6406 6405 6404
思路:这道题要用到异或的性质。就是j^k^j还是k
用lala[i]来表示根节点到i节点的异或值。(这里只有边权)然后就是两点之间的异或值就是lala[u]^lala[v]了。
还要用一下cnt【i】来表示从根节点到当前节点的异或值为i的有几个。
然后每一次一遍0~maxn扫一下就好了
有几个坑点:
1.当k==0的时候,这个时候自己跟自己还可以算。
所以先是求不包含自己的情况,cnt[i]*(cnt[i]-1),然后一定要/2,因为多算了两遍,再加上自己跟自己的。
不是0的话就是直接cnt[i]*cnt[i^k]/2就好了。
2.因为是从点开始的,所以在根节点时,异或值为0,cnt[0]++;
3.LL
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1000000+100;
typedef long long LL;
int cnt;
int lala[maxn],head[maxn];
LL num[maxn];
struct node{
int to,next,val;
}G[maxn<<1];
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
memset(lala,0,sizeof(lala));
memset(num,0,sizeof(num));
}
void add(int u,int v,int val){
G[++cnt].to=v;
G[cnt].next=head[u];
G[cnt].val=val;
head[u]=cnt;
}
void dfs(int u,int pre,int sum){
/// cout<<"***"<<endl;
for(int i=head[u];i!=-1;i=G[i].next){
int v=G[i].to;
if(v==pre)
continue;
lala[v]=sum^G[i].val;
/// cout<<"lala[v]:"<<lala[v]<<endl;
num[lala[v]]++;
dfs(v,u,lala[v]);
}
}
int main()
{
int t,n,a,b,c,m,k;
scanf("%d",&t);
while(t--){
init();
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d%d",&a,&b,&c);
add(a,b,c);add(b,a,c);
}
dfs(1,-1,0);
scanf("%d",&m);
LL ans=0;
num[0]++;
while(m--){
ans=0;
scanf("%d",&k);
for(int j=0;j<maxn;j++){
if(k==0)
ans+=(num[j]*(num[j]-1));
else
ans+=(num[j]*num[k^j]);
}
ans/=2;
if(k==0)
ans+=n;
printf("%I64d\n",ans);
}
}
}