Bakry遇到了一个问题,但由于他懒得解决它,他请求你的帮助。给你一个有n个节点的树,第i个节点的值为a,对于从1到n的每一个i都赋值给它。提醒一下,有n个节点的树是有n-1条边的连通图。你想从树中删除至少1条边,但最多k-1条边,这样下面的条件就成立了:对于每个连接的组件,计算其中节点值的逐位异或。然后,对于所有连接的组件,这些值必须相同。这个条件有可能实现吗?输入每个测试包含多个测试用例。第一行包含测试用例的数量t (1 <t< 5 - 104)。测试用例的描述每个测试用例的第一行包含两个整数n和k (2 < k < n <105)。每个测试用例的第二行包含n个整数a1,a2,。, an (1 < a;≤10°)。接下来n-1行的第i行包含两个整数u和v (1 < ui, vi < n, ui vi),这意味着在节点ui和v之间有一条边。可以保证给定的图是树。它保证所有测试用例的n和不超过2- 105。输出对于每个测试用例,您都应该输出一个字符串。如果你可以根据上面写的条件删除边,输出“YES”(不带引号)。否则,输出“NO”(不带引号)。您可以在任何情况下打印“YES”和“NO”的每个字母(大写或小写)。
Example
input
Copy
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
Copy
NO YES NO YES NO
题解:
题目问我们是否可以移除几条边,使各部分异或和相等
我们可以从异或的性质入手
如果所有点异或和为0,说明中间存在两个相等部分异或为0(两个相等的数异或为0)x ^ x = 0
若不为0, x ^ x ^ x = x
3 3 3
有三个或三个以上部分异或值 = 总体异或值
接着我们就dfs寻找,树中出现了几次这样的值,注意每次找到要清空那个树根的值
#include<iostream>
#include<string>
#include<vector>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
int a[100050];
int cnt;
int b[100050];
vector<int> p[100050];
int s = 0;
void dfs(int x,int fa)
{
b[x] = a[x];
for(auto ne:p[x])
{
if(ne == fa)
continue;
dfs(ne,x);
b[x] ^= b[ne];
}
if(b[x] == s)
{
cnt++;
b[x] = 0;
}
}
void solve()
{
int n,k;
cin >> n >> k;
cnt = 0;
s = 0;
for(int i = 1;i <= n;i++)
{
p[i].clear();
b[i] = 0;
}
for(int i = 1;i <= n;i++)
{
cin >> a[i];
s ^= a[i];
}
for(int i = 1;i < n;i++)
{
int x,y;
cin >> x >> y;
p[x].push_back(y);
p[y].push_back(x);
}
if(s == 0)
{
cout <<"YES\n";
}
else
{
dfs(1,-1);
if(k - 1 >= 2&&cnt >= 2)
{
cout <<"YES\n";
}
else
{
cout <<"NO\n";
}
}
}
signed main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);cout.tie(0);
int t = 1;
cin >> t;
// scanf("%lld",&t);
while (t--)
{
solve();
}
return 0;
}