标签:
题解链接:http://www.cygmasot.com/index.php/2015/08/20/hdu_5416/
题意:
给定n个点的树
下面n-1行给出边和边权
下面q个询问
每个询问一个数字s
询问有多少条路径使得路径的边权异或结果 == s 结果%(1e9+7)
询问不超过10组。
思路:
设路径{u,v}的边权异或结果为 f(u,v)
设lca 为u v的最近公共祖先
首先得到一个结论,f(u,v) =f(lca, u) ^ f(lca, v)
因为f(lca, root) ^ f(lca, root) == 0
所以 f(u,v) =( f(lca,u)^f(lca,root) ) ^ ( f(lca, v) ^ f(lca, root))
= f(root,u) ^ f(root, v)
然后用一个数组存下从根到任意一个点的路径异或值。
最后对每个询问,枚举以某个点为端点的路径个数即可。
因为这样算出来的path(u,v)是计算了2遍的,所以结果要/2
注意一下0的情况即可。
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #include <string.h> #include <limits.h> #include <vector> #include <string> #include <time.h> #include <math.h> #include <iomanip> #include <queue> #include <stack> #include <set> #include <map> template <class T> inline bool rd(T &ret) { char c; int sgn; if (c = getchar(), c == EOF) return 0; while (c != '-' && (c<'0' || c>'9')) c = getchar(); sgn = (c == '-') ? -1 : 1; ret = (c == '-') ? 0 : (c - '0'); while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0'); ret *= sgn; return 1; } template <class T> inline void pt(T x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) pt(x / 10); putchar(x % 10 + '0'); } using namespace std; const double eps = 1e-9; const double pi = acos(-1.0); const int N = 1e5 + 10; typedef long long ll; typedef pair<int, int> pii; struct Edge { int from, to, dis, nex; }edge[3 * N]; int head[N], edgenum; //fa[i][x] 是i的第2^x个父亲(如果超过范围就是根) void add(int u, int v, int w) { Edge E = { u,v,w,head[u] }; edge[edgenum] = E; head[u] = edgenum++; } void init() { memset(head, -1, sizeof head); edgenum = 0; } int n; int mp[N*2]; void dfs(int u, int fa, int dep) { mp[dep]++; for (int i = head[u]; ~i; i = edge[i].nex) { int v = edge[i].to; if (v == fa)continue; dfs(v, u, dep ^ edge[i].dis); } } ll ans; int s; void go(int u, int fa, int dep) { // mp[dep]--; ans += mp[s^dep]; for (int i = head[u]; ~i; i = edge[i].nex) { int v = edge[i].to; if (v == fa)continue; go(v, u, dep ^ edge[i].dis); } // mp[dep]++; } int main() { int T; rd(T); while (T--) { init(); rd(n); for (int i = 1, u, v, d; i < n; i++) { rd(u); rd(v); rd(d); add(u, v, d); add(v, u, d); } memset(mp, 0, sizeof mp); dfs(1, 1, 0); int Q; rd(Q); while (Q--) { rd(s); ans = 0; go(1, 1, 0); if (s == 0)ans += n; ans >>= 1; pt(ans); puts(""); } } return 0; }/* 1 2 1 2 0 10 0 */
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/qq574857122/article/details/47813351