给出一颗n个节点的无根树,和每个点的点权。
现在可以切开最少一条,最多K-1条边,使该数变成几棵子树。
问能否通过操作使每棵子树内点权的异或和相等。
先求出所有点的异或和,设为m。
如果m==0,那么任意切开一条边,获得的两棵子树的异或和都相等。(a xor a == 0)
如果m!=0,如果存在划分方案,则这些子树的异或和一定都为m,且为基数个。(m xor m xor m xor … xor m == m)
#include<bits/stdc++.h>
using namespace std;
#define maxn (int)1e5
#define read(a) scanf("%d",&a)
int n,K,m;
int a[maxn+5];
vector<int> tr[maxn+5];
bool use[maxn+5];
int s[maxn+5];
bool ans;
int dfs(int x) {
use[x]=true;
int cnt=0;
for(int i=0;i<tr[x].size();i++) {
int y=tr[x][i];
if(use[y]) continue;
cnt+=(dfs(y)>0);
s[x]^=s[y];
}
if(cnt>=2||(cnt&&!s[x])) ans=true;
if(s[x]==m) cnt++;
return cnt;
}
int main() {
int T;
read(T);
while(T--) {
ans=0,memset(use,0,sizeof(use));
for(int i=1;i<=n;i++) tr[i].clear();
read(n),read(K);
for(int i=1;i<=n;i++) read(a[i]),s[i]=a[i];
for(int i=1;i<n;i++) {
int x,y,z;
read(x),read(y);
tr[x].push_back(y);
tr[y].push_back(x);
}
m=0;
for(int i=1;i<=n;i++) m^=a[i];
if(m==0) {
printf("YES\n");
continue;
}
dfs(1);
if(ans&&K>=3) printf("YES\n");
else printf("NO\n");
}
return 0;
}