HDU 5416 CRB and Tree
题目大意:
T, T组测试数据
给你一个n有n个点,下标是从 1 开始的。这个是一棵树,然后下面是n-1条边,
每条边的信息是 s,e,w 代表 s-e的权值是w
然后是一个Q代表Q次询问。
每次询问是一个数字a, 代表 所有路径想异或后的值是 a的路径有多少条。
(注: 自己到自己的异或值是0,若a是0要考虑自己到自己)
题目分析:
从根节点开始进行一遍DFS求出所有点到 跟节点的异或值。也就得出来了根节点到达其他任何一个点的异或值。
比如 a 是跟节点到A的异或值, b是根节点到B的异或值
那么A->B的路径上的异或值就是 a^b.然后把所有的异或值桶排一下。
注意一点 a^b 的值是可能大于10W的,最大是260000多
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<vector> #include<queue> #include<cmath> using namespace std; #define INF 0x3fffffff typedef long long LL; const LL maxn = 300005; const LL mod = 1e9+7; bool vis[maxn]; int k, Head[maxn], n, Max = 0; LL num[maxn]; struct node { int e, next, w; }Edge[maxn*2]; void AddEdge(int s,int e,int w) { Edge[k].w = w; Edge[k].e = e; Edge[k].next = Head[s]; Head[s] = k; k ++; } void DFS(int root,int a) { vis[root] = true; num[a] ++; for(int i=Head[root]; i!=-1; i=Edge[i].next) { int e = Edge[i].e; if(vis[e] == true) continue; DFS(e, a^Edge[i].w); } } int main() { int Q, T; scanf("%d", &T); while(T--) { scanf("%d", &n); k = 0; memset(Head, -1, sizeof(Head)); memset(vis, false, sizeof(vis)); memset(num, 0, sizeof(num)); for(int i=0; i<n-1; i++) { int s, e, w; scanf("%d %d %d",&s, &e, &w); AddEdge(s, e, w); AddEdge(e, s, w); } DFS(1, 0); scanf("%d", &Q); while( Q --) { int a; LL ans = 0; scanf("%d", &a); if(a == 0) ans += n; for(int i=0; i<=270000; i++) { if(a == 0) ans += num[i]*(num[i]-1)/2; else if(i < (a^i) && num[i] && num[a^i]) ans += num[i]*num[a^i]; } printf("%lld\n", ans); } } return 0; }