题解链接: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