题意:给一棵树,每条边有一个权值,求满足u到v的路径上的异或和为s的(u,v)点对数
思路:计a到b的异或和为f(a,b),则f(a,b)=f(a,root)^f(b,root)。考虑dfs,一边计算当前点到根的f值,用一个数组记录当前遍历过的点中到根的异或值为i的点的个数,那么答案可以O(1)算出来,更新也是O(1)的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | #pragma comment(linker, "/STACK:10240000") #include <map> #include <set> #include <cmath> #include <ctime> #include <deque> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <string> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define X first #define Y second #define pb push_back #define mp make_pair #define all(a) (a).begin(), (a).end() #define fillchar(a, x) memset(a, x, sizeof(a)) #define copy(a, b) memcpy(a, b, sizeof(a)) typedef long long ll; typedef pair<int, int> pii; typedef unsigned long long ull; #ifndef ONLINE_JUDGE void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);} void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R> void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1; while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T> void print(const T t){cout<<t<<endl;}template<typename F,typename...R> void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T> void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;} #endif template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);} template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);} const double PI = acos(-1.0); const int INF = 1e9 + 7; const double EPS = 1e-12; /* -------------------------------------------------------------------------------- */ const int maxn = 2e5 + 7; struct Graph { vector<vector<int> > G; void clear() { G.clear(); } void resize(int n) { G.resize(n + 2); } void add(int u, int v) { G[u].push_back(v); } vector<int> & operator [] (int u) { return G[u]; } }; Graph G; struct Edge { int u, v, w; Edge(int u, int v, int w) { this->u = u; this->v = v; this->w = w; } }; vector<Edge> E; bool vis[maxn]; int cnt[maxn]; int Q[20]; ll ans[20]; int q, now; void add(int u, int v, int w) { E.pb(Edge(u, v, w)); G.add(u, E.size() - 1); } void dfs(int u) { cnt[now] ++; for (int i = 0; i < q; i ++) { ans[i] += cnt[now ^ Q[i]]; } vis[u] = true; for (int i = 0; i < G[u].size(); i ++) { Edge e = E[G[u][i]]; if (!vis[e.v]) { now ^= e.w; dfs(e.v); now ^= e.w; } } } int main() { #ifndef ONLINE_JUDGE freopen("in.txt", "r", stdin); //freopen("out.txt", "w", stdout); #endif // ONLINE_JUDGE int T, n; cin >> T; while (T --) { cin >> n; E.clear(); G.clear(); G.resize(n); for (int i = 1; i < n; i ++) { int u, v, w; scanf("%d%d%d", &u, &v, &w); add(u, v, w); add(v, u, w); } cin >> q; for (int i = 0; i < q; i ++) { scanf("%d", Q + i); } fillchar(vis, 0); now = 0; fillchar(cnt, 0); fillchar(ans, 0); dfs(1); for (int i = 0; i < q; i ++) { cout << ans[i] << endl; } } return 0; } |