【CodeForces 1592C】Bakry and Partitioning
阿新 • • 發佈:2021-11-19
連結:
題目大意:
一棵樹有 \(n\) 個節點,第 \(i\) 個節點的點權為 \(a_i\)。
你需要回答:能不能選擇這棵樹中的至少 \(1\) 條邊、至多 \(k-1\) 條邊刪除,使得刪除完這些邊的樹每個聯通塊的點權異或和相等。
思路:
\(a\oplus a=0\) 真的好用,就可以直接搜尋了。
程式碼:
const int N = 1e5 + 10; inline ll Read() { ll x = 0, f = 1; char c = getchar(); while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') f = -f, c = getchar(); while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar(); return x * f; } int t, n, k; int a[N]; int head[N], tot; struct edge { int to, nxt; }e[N << 1]; void Add(int u, int v) { e[++tot] = (edge) {v, head[u]}, head[u] = tot; } int cnt, xsum; int dfs(int u, int fa) { int ans = a[u]; for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v == fa) continue; int tmp = dfs(v, u); if (tmp == xsum) cnt++; else ans ^= tmp; } return ans; } int main() { // freopen(".in", "r", stdin); // freopen(".out", "w", stdout); for (t = Read(); t--; ) { n = Read(), k = Read(); xsum = cnt = tot = 0; for (int i = 1; i <= n; i++) xsum ^= a[i] = Read(); memset (head, 0, sizeof head); for (int i = 1; i < n; i++) { int u = Read(), v = Read(); Add(u, v), Add(v, u); } if (!xsum) puts("YES"); else { if (k >= 3) { dfs (1, 0); if (cnt >= 2) puts("YES"); else puts("NO"); } else puts("NO"); } } return 0; }