删除最多 P 条边后检查每个连接组件的 XOR 是否相等
给定一棵具有N个节点和一个整数P的树,任务是删除范围 [1, P) 内的边,并为形成的每个连接组件找到节点的 XOR。如果节点的值对于所有形成的连接组件都相等,则打印“YES”否则“NO”。
例子:
Input: N = 5, P = 5, Edges[][]={ { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 5 }}, nodes[] = {2, 2, 2, 2, 2}
Output: YES
Explanation: We can remove all edges, then there will be 5 connected components each having one node with value 2, thus XOR of each of them will be 2.
Input: N = 5, P = 2, Edges[][]={ { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 5 }}, nodes[] = {1, 6, 4, 1, 2}
Output: YES
Explanation: As, p = 2, atleast one edge need to be removed so, removing edge (4, 5), gives two connected components.
XOR of first component would be, arr1 XOR arr2 XOR arr3 XOR arr4= 1 XOR 6 XOR 4 XOR 1 => 2.
XOR of second component will be arr5 = 2. (Thus, both equal).
方法:解决此问题的方法基于以下观察:
The fact here, is that deletion of edges should be either once or twice, as:
- Removing one edge gives us 2 connected components, which should have same XOR and thus by properties of xor if XOR1 == XOR2, then XOR1 ^ XOR2 = 0, where ^ is the bitwise XOR.
- Similarly, if XOR of the whole tree is 0, removing any edge, will give 2 connected components where both components would have equal value, thus answer = “YES”.
- Now, if we delete 2 edges, deleting more than that would just merge the other components with each other. For ex: if there are 4 or more connected components, we can reduce and merge them, as for 4 it can be reduced to 2 components (which will fall in the case if we remove 1 edge).
- Now, deleting 2 edges gives us a minimum of 3 connected components, using properties of xor we know, that XOR1 ^ XOR2 ^ XOR3 = let’s say some value(y), which means we need to find such subtrees(or say search for 2 edges to remove) whose XOR is equal to some value(y), and if we find it then answer = “YES” else “NO”, such that p>2.
- For ex: say, if we have total XOR = some value(y), with N = 4, there can be 3 segments whose XOR would have been y, then the total elements could get XOR = y, such that p > 2.
So, overall it can be said that if we find two subtrees whose XOR = y, and if our total XOR was y, we can say that our left out component/segment XOR would also be y, thus answer = “YES”, such that p > 2, using above property XOR1 ^ XOR2 ^ XOR3 = some value(y),
请按照以下步骤应用上述方法:
要找到这样的子树,至少有 3 个连接的组件,可以使用 DFS 遍历轻松完成,并且在回溯期间,我们将在每次迭代时存储每个索引 XOR。
下面是上述方法的实现:
C++
// C++ code for Check after removing
// edges bitwise XOR of each connected
// component formed is equal
#include
using namespace std;
const int N = 1e5;
// adjacency list to form a tree
vector adj[N];
// array arr defined to store node values
// array cal_XOR defined to store
// xor values rooted at i'th level
int nodes[N], cal_XOR[N];
// defined a visited array
vector visited(N);
// defined a counter to store
// number of subtrees having value equal
// to whole tree XOR
int counter = 0;
// first dfs function to find
// xor of subtrees
int dfs_First(int x)
{
// initializing cal_XOR
// array with tree node's value
cal_XOR[x] = nodes[x];
// marking each visited node as true
visited[x] = true;
// iterating through current node children
for (auto y : adj[x]) {
// check if node->child is not visited
if (!visited[y]) {
// computing xor of subtree rooted at x
cal_XOR[x] ^= dfs_First(y);
}
}
// returning xor of subtree rooted at x
return cal_XOR[x];
}
// second dfs function to count
// subtrees having values equal
// to entire XOR of tree nodes values
// and returning subtree XOR till that point
int dfs_Second(int x)
{
// marking each visited node as true
visited[x] = true;
// storing value of nodes[x]
// to another variable temp
// for further calculation
int temp = nodes[x];
// iterating through current node children
for (auto y : adj[x]) {
// check if node->child is not visited
if (!visited[y]) {
// storing xor of subtree
temp ^= dfs_Second(y);
}
}
// now, checking if xor of subtree
// computed till now is equal to
// entire XOR of tree (root)
// i.e. value at cal_XOR[0] ->
// which will give entire XOR of the tree
if (temp == cal_XOR[0]) {
// then, make that xor 0
temp = 0;
// increase count by 1, which
// means we found a subtree
counter++;
}
// return xor of subtree
// till that point
return temp;
}
// Function to add edges
void addEdge(int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
// Function to take input
// for (n-1) edges
void init(int edges[4][2], int numEdges)
{
for (int i = 0; i < numEdges; i++) {
edges[i][0]--;
edges[i][1]--;
addEdge(edges[i][0], edges[i][1]);
}
}
// Driver Code
int main()
{
// taking input
int n = 5, p = 2;
nodes[0] = 1, nodes[1] = 6, nodes[2] = 4,
nodes[3] = 1, nodes[4] = 2;
// making our visited array false
for (int i = 0; i < n; i++) {
visited[i] = false;
}
// taking input for (n-1) edges
int edges[4][2]
= { { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 5 } };
init(edges, 4);
// First dfs Function call
dfs_First(0);
// again, marking visited array to false
for (int i = 0; i < n; i++) {
visited[i] = false;
}
// initializing answer variable
bool answer = false;
// if we found XOR of entire tree
// equal to zero, answer = "YES", as
// it means there are two connected
// components equal to each other
// thus, a single edge can be removed
if (cal_XOR[0] == 0) {
answer = true;
}
else {
// second DFS function call
dfs_Second(0);
// if we found 2 subtree having
// equal value with XOR of entire tree
// answer is always "YES", such that
// p > 2
if (counter >= 2 and p != 2) {
answer = true;
}
}
// printing the final answer
if (answer == true) {
cout << "YES"
<< "\n";
}
else {
cout << "NO"
<< "\n";
}
// making counter = 0 for next iteration
counter = 0;
for (int i = 0; i < n; i++) {
// similarly clearing adjacency list
// and both arr and cal_XOR array
adj[i].clear();
cal_XOR[i] = nodes[i] = 0;
}
}
Javascript
YES
时间复杂度: O(N+E),其中 N= 节点数,E = 边数
辅助空间: O(N+E),其中 N= 节点数,E = 边数