diff --git a/04- April/README.md b/04- April/README.md index 0e2635750..3fa254dcf 100644 --- a/04- April/README.md +++ b/04- April/README.md @@ -51,6 +51,7 @@ 1. **[Add Digits](#26--add-digits)** 1. **[Bulb Switcher](#27--bulb-switcher)** 1. **[Similar String Groups](#28--similar-string-groups)** +1. **[Checking Existence of Edge Length Limited Paths](#29--checking-existence-of-edge-length-limited-paths)** 1. **[Remove Max Number of Edges to Keep Graph Fully Traversable](#30--remove-max-number-of-edges-to-keep-graph-fully-traversable)**
@@ -1632,6 +1633,219 @@ public: }; ``` + +
+

+ +## 29) [Checking Existence of Edge Length Limited Paths](https://leetcode.com/problems/checking-existence-of-edge-length-limited-paths/) + +### Difficulty + +![](https://img.shields.io/badge/Hard-red?style=for-the-badge) + +### Related Topic + +`Union Find` `Graph` `Array` `Sorting` + +### Code + + +```cpp +template +struct DSU { + vector parent, Gsize; + + // Constructor to initialize the parent and Gsize vectors. + DSU(int MaxNodes) { + parent = Gsize = vector(MaxNodes + 5); + for (int i = Base; i <= MaxNodes; i++) + parent[i] = i, Gsize[i] = 1; + } + + // Find the leader of the set where 'node' belongs and compress the path while traversing. + T find_leader(int node) { + return parent[node] = (parent[node] == node ? node : find_leader(parent[node])); + } + + // Check if 'u' and 'v' belong to the same set or not. + bool is_same_sets(int u, int v) { + return find_leader(u) == find_leader(v); + } + + // Merge the sets containing 'u' and 'v'. + void union_sets(int u, int v) { + int leader_u = find_leader(u), leader_v = find_leader(v); + if (leader_u == leader_v) + return; + if (Gsize[leader_u] < Gsize[leader_v]) + swap(leader_u, leader_v); + Gsize[leader_u] += Gsize[leader_v], parent[leader_v] = leader_u; + } + + // Get the size of the set where 'u' belongs. + int get_size(int u) { + return Gsize[find_leader(u)]; + } +}; + +// Define a template struct called LCA +// that takes an optional typename T (default to int) +template +struct LCA { + + // Define an inner struct called Edge + // that has a vertex v and a weight w + struct Edge { + T v, w; + + Edge(T V = 0, T W = 0) : v(V), w(W) {} + + bool operator < (const Edge &rhs) const { + return w < rhs.w; + } + }; + + // Initialize variables + int N, LOG; + vector < vector > anc, cost; + vector < vector > adj; + vector dep, vis; + + // Constructor for LCA + LCA(int n){ + // Set N to n + 10 and find the LOG of N + N = n + 10, LOG = 0; + while((1 << LOG) <= N) LOG++; + // Initialize dep, vis, adj, anc, and cost vectors + dep = vis = vector (N); + adj = vector < vector > (N); + anc = cost = vector < vector > (N, vector (LOG)); + } + + // Add edge to the graph + void add_edge(int u, int v, T w){ + adj[u].push_back(Edge(v, w)); + adj[v].push_back(Edge(u, w)); + } + + // Build adjacency list from input + void build_adj(int edges){ + for(int i = 0, u, v, w; i < edges && cin >> u >> v >> w; i++) + add_edge(u, v, w); + } + + // Operation to be performed on cost + T operation(T a, T b){ + return max(a, b); + } + + // Perform depth-first search on the graph + void dfs(int u){ + vis[u] = true; + for(auto& [v, w] : adj[u]){ + if(vis[v]) continue; + dep[v] = dep[u] + 1, anc[v][0] = u, cost[v][0] = w; + for(int bit = 1; bit < LOG; bit++){ + anc[v][bit] = anc[anc[v][bit - 1]][bit - 1]; + cost[v][bit] = operation(cost[v][bit - 1], cost[anc[v][bit - 1]][bit - 1]); + } + dfs(v); + } + } + + // Find the kth ancestor of a node + int kth_ancestor(int u, int k){ + if(dep[u] < k) + return -1; + for(int bit = LOG - 1; bit >= 0; bit--) + if(k & (1 << bit)) + u = anc[u][bit]; + return u; + } + + // Find the lowest common ancestor of two nodes + int get_lca(int u, int v){ + if(dep[u] < dep[v]) + swap(u, v); + u = kth_ancestor(u, dep[u] - dep[v]); + if(u == v) + return u; + for(int bit = LOG - 1; bit >= 0; bit--) + if(anc[u][bit] != anc[v][bit]) + u = anc[u][bit], v = anc[v][bit]; + return anc[u][0]; + } + + // Get the cost from a node to its ancestor at a certain distance + T get_cost(int u, int dist){ + if(dep[u] < dist) return -1; + T ans = 0; + for(int bit = 0; bit < LOG; bit++) + if(dist & (1 << bit)) + ans = operation(ans, cost[u][bit]), u = anc[u][bit]; + return ans; + } + + // Function to answer LCA queries between two nodes u and v + T query(int u, int v){ + int lca = get_lca(u, v); + return operation(get_cost(u, dep[u] - dep[lca]), get_cost(v, dep[v] - dep[lca])); + } + + // Function to build the LCA tree + void build(int n){ + for(int i = 1; i <= n; i++) + if(!vis[i]) + dfs(i); + } + +}; + +class Solution { +public: + // Define a function that takes in an integer n, a vector of vectors of integers edgeList, and a vector of vectors of integers queries and returns a vector of bools. + vector < bool > distanceLimitedPathsExist(int n, vector < vector < int > >& edgeList, vector < vector < int > >& queries) { + // Sort the edges by their weights. + sort(edgeList.begin(), edgeList.end(), [&](vector < int >& a, vector < int >& b){ + return a[2] < b[2]; + }); + + // Create an instance of a disjoint set union data structure (DSU) and a lowest common ancestor (LCA) data structure. + DSU < int > dsu(n); + LCA < int > lca(n); + + // Iterate through the sorted edges and add each edge to the LCA data structure if the nodes it connects are not in the same set in the DSU. + // make mst for the graph + for(auto& edge : edgeList){ + int u = ++edge[0], v = ++edge[1], w = edge[2]; + if(dsu.is_same_sets(u, v)) continue; + dsu.union_sets(u, v); + lca.add_edge(u, v, w); + } + + // Build the LCA data structure. + lca.build(n); + + // Create a vector to store the answers to the queries. + vector < bool > ans; + + // Iterate through the queries and check if the nodes it connects are in the same set in the DSU. + // If they are, check if the minimum edge weight on the path between them is less than the query limit. + // If they are not in the same set, it is impossible to have a path between them. + // Add the answer to the answer vector. + for(auto& q : queries){ + int u = ++q[0], v = ++q[1], limit = q[2]; + if(dsu.is_same_sets(u, v)) + ans.push_back(lca.query(u, v) < limit); + else + ans.push_back(false); + } + + // Return the answer vector. + return ans; + } +}; +```


@@ -1725,4 +1939,4 @@ public: } }; ``` - \ No newline at end of file +