From 9a4d7a0939ceaa7339836625e4ca0a5c19a2244d Mon Sep 17 00:00:00 2001
From: Ahmed Hossam <63050133+7oSkaaa@users.noreply.github.com>
Date: Sun, 30 Apr 2023 12:59:09 +0200
Subject: [PATCH] Update README.md
---
04- April/README.md | 216 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 215 insertions(+), 1 deletion(-)
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
+