Skip to main content

Incremental Even-Weighted Cycle Queries - Solution & Explanation

HardUnion FindGraph4 min read
Practice this problem

Problem Statement

You are given a positive integer n.

There is an undirected graph with n nodes labeled from 0 to n - 1. Initially, the graph has no edges.

You are also given a 2D integer array edges, where edges[i] = [ui, vi, wi] represents an edge between nodes ui and vi with weight wi. The weight wi is either 0 or 1.

Process the edges in edges in the given order. For each edge, add it to the graph only if, after adding it, the sum of the weights of the edges in every cycle in the resulting graph is even.

Return an integer denoting the number of edges that are successfully added to the graph.

 

Example 1:

Input: n = 3, edges = [[0,1,1],[1,2,1],[0,2,1]]

Output: 2

Explanation:

  • [0, 1, 1]: We add the edge between vertex 0 and vertex 1 with weight 1.
  • [1, 2, 1]: We add the edge between vertex 1 and vertex 2 with weight 1.
  • [0, 2, 1]: The edge between vertex 0 and vertex 2 (the dashed edge in the diagram) is not added because the cycle 0 - 1 - 2 - 0 has total edge weight 1 + 1 + 1 = 3, which is an odd number.

Example 2:

Input: n = 3, edges = [[0,1,1],[1,2,1],[0,2,0]]

Output: 3

Explanation:

  • [0, 1, 1]: We add the edge between vertex 0 and vertex 1 with weight 1.
  • [1, 2, 1]: We add the edge between vertex 1 and vertex 2 with weight 1.
  • [0, 2, 0]: We add the edge between vertex 0 and vertex 2 with weight 0.
  • Note that the cycle 0 - 1 - 2 - 0 has total edge weight 1 + 1 + 0 = 2, which is an even number.

 

Constraints:

  • 3 <= n <= 5 * 104
  • 1 <= edges.length <= 5 * 104
  • edges[i] = [ui, vi, wi]
  • 0 <= ui < vi < n
  • All edges are distinct.
  • wi = 0 or wi = 1

Approach Overview

Problem Overview: You process graph queries where edges are added incrementally. After each insertion, determine whether the new edge forms a cycle whose total weight is even. The challenge is answering these checks efficiently without recomputing paths for every query.

Approach 1: Recompute Cycle Using DFS/BFS (Brute Force) (Time: O(Q * (V + E)), Space: O(V + E))

For each query, temporarily add the edge and search for an existing path between the two endpoints using DFS or BFS. While traversing, accumulate the path weight parity (even or odd). If a path already exists and the combined parity with the new edge results in an even total, the edge closes an even-weighted cycle. This method repeatedly scans the graph, so performance degrades quickly when the number of queries grows. It works for small graphs or when queries are limited.

Approach 2: Maintain Prefix Parity with Graph Traversal (Time: O(V + E) preprocessing + O(path length) per query, Space: O(V))

Store parity information for paths relative to a chosen root using a traversal such as BFS. When a query connects two nodes, compare their stored parity values and combine with the edge weight parity to determine the resulting cycle parity. The issue is maintaining correctness after many incremental insertions, since new edges can invalidate previously computed parity paths. This technique works only if the graph structure remains mostly static.

Approach 3: Disjoint Set Union with Parity Tracking (Optimal) (Time: O((N + Q) α(N)), Space: O(N))

Use a Union-Find (Disjoint Set Union) structure where each node stores the parity of the path to its parent. During find(), path compression updates parity relative to the root. When inserting an edge (u, v, w), check whether both nodes already share the same root. If they do, the parity difference between u and v combined with the new edge weight reveals whether the formed cycle has even weight. If the roots differ, merge them while preserving parity constraints. This approach processes queries almost in constant time due to the inverse Ackermann factor.

Parity handling is essentially an XOR operation on weight mod 2. The DSU maintains the parity from each node to its root, so the parity between any two nodes can be derived quickly. This pattern also appears in problems involving bipartite constraints and XOR relationships, commonly implemented with graph reasoning and disjoint set union structures.

Recommended for interviews: Start by describing the brute-force path search to show you understand the cycle detection requirement. Then move to DSU with parity tracking. Interviewers expect the union-find optimization because it handles incremental connectivity queries efficiently while maintaining parity constraints.

Solutions for this problem are being prepared.

Try solving it yourself

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
DFS/BFS per QueryO(Q * (V + E))O(V + E)Small graphs or when query count is very low
Traversal with Stored ParityO(V + E) + per-query traversalO(V)Mostly static graphs with limited incremental updates
Union-Find with Parity (Optimal)O((N + Q) α(N))O(N)Large graphs and many incremental queries

Video Solution

LeetCode Weekly Contest 495 - Q4 - Incremental Even-Weighted Cycle Queries (3887) ExplainedKumar K [Amazon]1,357 views views

Watch 5 more video solutions →

Frequently Asked Questions

Is Incremental Even-Weighted Cycle Queries easy or hard?
Incremental Even-Weighted Cycle Queries is generally classified as a hard problem because it combines dynamic graph updates with parity constraints. Understanding DSU with extra state (parity or XOR) is required to achieve the optimal near-constant time solution.
Incremental Even-Weighted Cycle Queries Python/Java solution
Both Python and Java implementations typically use arrays for parent, rank, and parity. The find operation performs path compression while updating parity relative to the root. During union, the parity relationship between the two components is adjusted based on the edge weight modulo 2.
How to solve Incremental Even-Weighted Cycle Queries in O(n)?
Maintain a Union-Find structure where each node keeps the parity of the path to its parent (weight mod 2). When processing a query edge (u, v, w), compare the parity from both nodes to their root and combine it with w. If the nodes already share a root, you can determine immediately whether the resulting cycle has even total weight.
What is the best approach for Incremental Even-Weighted Cycle Queries?
The most efficient solution uses Disjoint Set Union (Union-Find) with parity tracking. Each node stores the parity of the path to its root, allowing the algorithm to quickly determine whether adding an edge forms an even-weighted cycle. The amortized complexity is O((n + q) α(n)), which is effectively constant time per query in practice.
Is Incremental Even-Weighted Cycle Queries asked at Google/Amazon/Meta?
Problems combining Union-Find with parity or XOR constraints frequently appear in interviews at companies like Google, Amazon, and Meta. Variants include checking bipartiteness with constraints, XOR equations between nodes, and cycle parity detection in dynamic graphs.
What data structure is used in Incremental Even-Weighted Cycle Queries?
The core data structure is Disjoint Set Union (Union-Find) enhanced with parity tracking. Each node stores its parent and a parity bit representing the weight parity to the root. Path compression and union by rank keep operations efficient.
What is the time complexity of Incremental Even-Weighted Cycle Queries?
The optimal DSU-based solution runs in O((n + q) α(n)) time, where α(n) is the inverse Ackermann function. This makes each union and find operation nearly constant time. Space complexity is O(n) for storing parent and parity arrays.

Ready to solve this problem?

Practice Incremental Even-Weighted Cycle Queries with our built-in code editor and test cases.

Practice on FleetCode