题目 C. Bakry and Partitioning
Bakry and Partitioning
Bakry faced a problem, but since he’s lazy to solve it, he asks for your help.
You are given a tree of n nodes, the i-th node has value ai assigned to it for each i from 1 to n. As a reminder, a tree on n nodes is a connected graph with n−1 edges.
You want to delete at least 1, but at most k−1 edges from the tree, so that the following condition would hold:
For every connected component calculate the bitwise XOR of the values of the nodes in it. Then, these values have to be the same for all connected components.
Is it possible to achieve this condition?
Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤5⋅104). Description of the test cases follows.
The first line of each test case contains two integers n and k (2≤k≤n≤105).
The second line of each test case contains n integers a1,a2,…,an (1≤ai≤109).
The i-th of the next n−1 lines contains two integers ui and vi (1≤ui,vi≤n, ui≠vi), which means that there’s an edge between nodes ui and vi.
It is guaranteed that the given graph is a tree.
It is guaranteed that the sum of n over all test cases doesn’t exceed 2⋅105.
Output
For each test case, you should output a single string. If you can delete the edges according to the conditions written above, output “YES” (without quotes). Otherwise, output “NO” (without quotes).
You can print each letter of “YES” and “NO” in any case (upper or lower).
Example
input
5
2 2
1 3
1 2
5 5
3 3 3 3 3
1 2
2 3
1 4
4 5
5 2
1 7 2 3 5
1 2
2 3
1 4
4 5
5 3
1 6 4 1 2
1 2
2 3
1 4
4 5
3 3
1 7 4
1 2
2 3
output
NO
YES
NO
YES
NO
Note
It can be shown that the objection is not achievable for first, third, and fifth test cases.
In the second test case, you can just remove all the edges. There will be 5 connected components, each containing only one node with value 3, so the bitwise XORs will be 3 for all of them.
In the fourth test case, this is the tree:
You can remove an edge (4,5)
The bitwise XOR of the first component will be, a1⊕a2⊕a3⊕a4=1⊕6⊕4⊕1=2 (where ⊕ denotes the bitwise XOR).
The bitwise XOR of the second component will be, a5=2.
题意:
在至少一次,最多k-1次操作以内,是否能将当前树分为几个连通块,将这几个连通块内所有点的值进行异或,使得每个连通块的异或和相同。
思路:
可行方案分两种(即输出YES):
1.当前不进行操作时,所有值的异或和为0(此种任取一个数出来剩下的异或和都与此数相等,只需要一次操作,一定可行)。
2.所有值异或和不为0时,假设为x,则至少分成三个异或和为x的连通块(dfs搜索,异或和为x的连通块数量>=3并且k-1>=3即可)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<math.h>
#include<vector>
#include<algorithm>
const int N=1e6+10;
using namespace std;
int t;
int n,k;
int a[N];//当前节点的值
int sum;//所有值异或和
int cnt;//连通块异或和为sum的数量
vector<int>g[N];
int dfs(int x,int p)
{
int t=a[x];
for(int i:g[x])
{
if(p!=i)t^=dfs(i,x);//当前i即g[x][i]
}
// 上下两种写法相同
// for(int i=0;i<g[x].size();i++)
// {
// if(p!=g[x][i])t^=dfs(g[x][i],x);
// }
if(t==sum){
t=0;
cnt++;
}
return t;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>k;
//初始化
for(int i=0;i<=n;i++)
g[i].clear();
sum=0;
cnt=0;
for(int i=1;i<=n;i++){
cin>>a[i];
sum^=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,1);
if((cnt>=3&&k>=3)||sum==0)cout<<"YES"<<endl;//可行的两种情况
else cout<<"NO"<<endl;
}
return 0;
}
感谢浏览~