#include<bits/stdc++.h> usingnamespace std; constint N = 2e5 + 10; int n; vector<int> G[N]; int a[N], dis[N]; voiddfs(int u, int fa){ dis[u] = a[u]; if(fa) dis[u] ^= dis[fa]; for (auto v : G[u]) { if(v != fa) dfs(v, u); } } set<int> s[N]; // 快速查找有无 0 路径 voidmove(int u, int v){ // 合并 for (auto x : s[u]) s[v].insert(x); s[u].clear(); } int ans = 0; voiddfs2(int u, int fa){ bool mark = 0; s[u].insert(dis[u]); for (auto v : G[u]) { if(v != fa) { dfs2(v, u); if(s[u].size() < s[v].size()) swap(s[u], s[v]); // 保证是小的合并至大的里面【启发式合并】 for (auto x : s[v]) mark |= s[u].count(x ^ a[u]); // 如果存在 dis[u] = x ^ a[u] 说明子树中存在异或路径为 0 的路径 move(v, u); } } if(mark) ans ++, s[u].clear(); // 如果存在,那么该节点需要删除 }
signedmain(){ ios::sync_with_stdio(0); cin >> n; for (int i = 1; i <= n; i ++) cin >> a[i]; for (int i = 1; i < n; i ++) { int u, v; cin >> u >> v, G[u].push_back(v), G[v].push_back(u); } dfs(1, 0); dfs2(1, 0); cout << ans << endl; return0; }
constint N = 2e5 + 10; int n, m, k; vector< pi > G[N]; ll dis[N]; bool vis[N]; int li[N]; ll dijkstra(int pos, int val){ // pos 表示 二进制的第几位,val表示是1为S集还是 0 为 S 集 priority_queue<pi, vector<pi>, greater<pi> > q; memset(dis, 0x3f, sizeof dis); memset(vis, 0, sizeof vis); for (int i = 1; i <= k; i ++) { int x = li[i]; if(((x >> (pos - 1)) & 1) == val) { dis[x] = 0; q.push({0, x}); } } while(!q.empty()) { int u = q.top().second; q.pop(); if(vis[u]) continue; vis[u] = 1; for (auto e : G[u]) { int v = e.first, w = e.second; if(dis[u] + w < dis[v]) { dis[v] = dis[u] + w; q.push({dis[v], v}); } } } ll minn = 0x3f3f3f3f3f3f3f3f; for (int i = 1; i <= k; i ++) { int x = li[i]; if(((x >> (pos - 1)) & 1) != val) { minn = min(dis[x], minn); } } return minn; }
signedmain(){ ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int t; cin >> t; while(t --) { cin >> n >> m; for (int i = 1; i <= n; i ++) G[i].clear(); for (int i = 1; i <= m; i ++) { int u, v, w; cin >> u >> v >> w; G[u].push_back({v, w}); } cin >> k; for (int i = 1; i <= k; i ++) cin >> li[i]; ll ans = 0x3f3f3f3f3f3f3f3f; for (int i = 0; i < 24; i ++) { // 枚举二进制位数 ans = min(ans, dijkstra(i, 0)); ans = min(ans, dijkstra(i, 1)); } if(ans == 0x3f3f3f3f3f3f3f3f) cout << -1 << '\n'; else cout << ans << '\n'; } return0; }
voiddfs(int u, int f){ dep[u] = dep[f] + 1, fa[u][0] = f, len[u][0] = e[u][f]; for (int i = 1; ; i ++) { fa[u][i] = fa[fa[u][i - 1]][i - 1]; len[u][i] = len[fa[u][i - 1]][i - 1] + len[u][i - 1]; // 预处理 if (fa[u][i] == 0) { k = max(k, i - 1); break; } } for (auto v : g[u]){ if(v != f){ dfs(v, u); } } } intlca(int u, int v){ if(dep[u] < dep[v]) swap(u, v); int x = u, y = v; int lu = 0, lv = 0; // 统计两边跳的距离 for (int i = k; i >= 0; i --){ if(dep[fa[u][i]] >= dep[v]) lu += len[u][i], u = fa[u][i]; } if(u == v) return lu + lv; for (int i = k; i >= 0; i --){ if(fa[u][i] != fa[v][i]) lu += len[u][i], u = fa[u][i], lv += len[v][i], v = fa[v][i]; } lu += len[u][0], lv += len[v][0]; return lu + lv; }