有一颗树,问你能不能分成至少2个至多k个连通分量,并且每个连通分量的异或值都相同。
解析设每个点的异或之和为xo
- 根据异或的性质,如果xo为0,那么说明可以分成两个区间,其两个区间的异或之和一定为0。
- 如果xo不为0,我们要分成m个区间,每个区间为xo,如果我们能分成10个区间,那么一定能分成8个区间,因为我们可以选择相邻的三个连通分量构成一个大连通分量,其异或值还是为xo,因此,我们最后分成的奇数个连通分量的最小值是3。
- 现在题目转化成,能不能分成3个连通分量,异或值相同。
- 思路很简单,dfs遍历每个点的所有子树,如果其自身和子树的异或之和为xo,那么就断链并且记录个数cnt++,断链的方式就是给父节点返回0。
- 如果最后cnt>=3 && k>=3 那么表示满足题意。
#includetypedef long long ll; using namespace std; const int N=1e5+5; vector g[N]; int r[N]; int xo=0,cnt=0; void init(int n){ xo=0; cnt=0; for(int i=0;i<=n;i++){ g[i].clear(); } } int dfs(int x,int pre){ int son=r[x]; for(int j:g[x]){ if(pre!=j){ son^=dfs(j,x); } } if(son==xo){ son=0; cnt++; } return son; } void solve(){ int n,m; scanf("%d%d",&n,&m); init(n); for(int i=1;i<=n;i++){ scanf("%d",&r[i]); xo=xo^r[i]; } for(int i=1;i =3 && m>=3) || xo==0){ puts("YES"); } else{ puts("NO"); } } int main() { int t ; scanf("%d",&t); while(t--){ solve(); } return 0; }



