标签:
题目链接:
题目描述:
给一棵树有n个节点,树上的每条边都有一个权值。f(u,v)代表从u到v路径上所有边权的异或值,问满足f(u,v)==m的(u, v)有多少中情况(u, v有可能相同)?
解题思路:
由于xor的特殊性质。x^x=0,对于求f(u, v) == f(u, 1) ^ f(1, u)。 又因为x^y == z可以推出x^z == y,对于f(u, 1) ^ f(1, v) == m可以转化为m ^ f(1, v) == f(u, 1)。
可以先遍历一遍树,然后记录下来根节点到每个节点所经过路径的xor值,hash保存xor值出现的次数,然后枚举节点v即可。复杂度O(n*q)
hash表要开到pow(2,18)左右,如果小的话会wa。
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 using namespace std; 7 8 typedef long long LL; 9 const int maxn = 300000; 10 struct node 11 { 12 int to, next, w; 13 }edge[maxn]; 14 15 int arr[maxn], ans[maxn]; 16 int head[maxn], tot; 17 18 void Add (int from, int to, int w) 19 { 20 edge[tot].to = to; 21 edge[tot].w = w; 22 edge[tot].next = head[from]; 23 head[from] = tot++; 24 } 25 void bfs () 26 { 27 queue <int> Q; 28 Q.push(1); 29 arr[1] = 0; 30 while (!Q.empty()) 31 { 32 int u = Q.front (); 33 Q.pop(); 34 for (int i=head[u]; i!=-1; i=edge[i].next) 35 { 36 int v = edge[i].to; 37 if (arr[v] == -1) 38 { 39 arr[v] = arr[u] ^ edge[i].w; 40 Q.push(v); 41 } 42 } 43 } 44 } 45 46 int main () 47 { 48 int t, n, q, m; 49 scanf ("%d", &t); 50 while (t --) 51 { 52 memset (head, -1, sizeof(head)); 53 memset (ans, 0, sizeof(ans)); 54 memset (arr, -1, sizeof(arr)); 55 tot = 0; 56 57 scanf ("%d", &n); 58 for (int i=1; i<n; i++) 59 { 60 int x, y, z; 61 scanf ("%d %d %d", &x, &y, &z); 62 Add (x, y, z); 63 Add (y, x, z); 64 } 65 66 bfs (); 67 for (int i=1; i<=n; i++) 68 ans[arr[i]] ++; 69 70 scanf ("%d", &q); 71 while (q --) 72 { 73 LL res = 0; 74 scanf ("%d", &m); 75 for (int i=1; i<=n; i++) 76 res += ans[m^arr[i]]; 77 if (m == 0) 78 res += n; 79 printf ("%lld\n", res/2); 80 } 81 } 82 return 0; 83 }
标签:
原文地址:http://www.cnblogs.com/alihenaixiao/p/4747356.html