From 60198d23e6fc1dc9816d0a295035f8f4ca6b917f Mon Sep 17 00:00:00 2001 From: Mayur-nimkande-20 Date: Wed, 23 Oct 2024 18:56:40 +0530 Subject: [PATCH] Add graphs basics folder --- C++/Graphs_Basix/CHEAT_SHEET.md | 129 ++++++++++++++++++++ C++/Graphs_Basix/codes/bellman_ford.cpp | 53 ++++++++ C++/Graphs_Basix/codes/bfs.cpp | 45 +++++++ C++/Graphs_Basix/codes/dfs.cpp | 37 ++++++ C++/Graphs_Basix/codes/dijkstra.cpp | 51 ++++++++ C++/Graphs_Basix/codes/floyd_warshall.cpp | 88 +++++++++++++ C++/Graphs_Basix/codes/kruskal.cpp | 71 +++++++++++ C++/Graphs_Basix/codes/prims.cpp | 66 ++++++++++ C++/Graphs_Basix/codes/topological_sort.cpp | 52 ++++++++ C++/Graphs_Basix/question.md | 9 ++ 10 files changed, 601 insertions(+) create mode 100644 C++/Graphs_Basix/CHEAT_SHEET.md create mode 100644 C++/Graphs_Basix/codes/bellman_ford.cpp create mode 100644 C++/Graphs_Basix/codes/bfs.cpp create mode 100644 C++/Graphs_Basix/codes/dfs.cpp create mode 100644 C++/Graphs_Basix/codes/dijkstra.cpp create mode 100644 C++/Graphs_Basix/codes/floyd_warshall.cpp create mode 100644 C++/Graphs_Basix/codes/kruskal.cpp create mode 100644 C++/Graphs_Basix/codes/prims.cpp create mode 100644 C++/Graphs_Basix/codes/topological_sort.cpp create mode 100644 C++/Graphs_Basix/question.md diff --git a/C++/Graphs_Basix/CHEAT_SHEET.md b/C++/Graphs_Basix/CHEAT_SHEET.md new file mode 100644 index 0000000..92c756d --- /dev/null +++ b/C++/Graphs_Basix/CHEAT_SHEET.md @@ -0,0 +1,129 @@ + +# Graph Data Structure Cheat Sheet + +## 1. What is a Graph? +A **Graph** is a data structure consisting of a set of nodes (or vertices) and edges that connect these nodes. + +- **Vertices (V)**: Individual entities in the graph. +- **Edges (E)**: Connections between two vertices. + +A graph is represented as **G(V, E)**, where: +- **V** is a set of vertices +- **E** is a set of edges + +### Types of Graphs: +1. **Directed Graph (Digraph)**: Edges have direction (u → v). +2. **Undirected Graph**: Edges are bidirectional (u ↔ v). +3. **Weighted Graph**: Edges have weights or costs associated with them. +4. **Unweighted Graph**: All edges have the same weight or no weight at all. + +### Common Terminologies: +- **Adjacency**: Two vertices are adjacent if they are connected by an edge. +- **Degree**: The number of edges connected to a vertex. +- **Path**: A sequence of vertices where each adjacent pair is connected by an edge. +- **Cycle**: A path where the first and last vertices are the same. + +## 2. Graph Representation + +### 2.1 Adjacency Matrix +An `N x N` matrix is used to represent the graph where `N` is the number of vertices. +- **adj[i][j] = 1** if there is an edge from vertex `i` to vertex `j`. +- **adj[i][j] = 0** otherwise. + +### 2.2 Adjacency List +Each vertex has a list of all vertices it is connected to. This representation is more space-efficient for sparse graphs. + +## 3. Graph Traversal + +### 3.1 Breadth-First Search (BFS) +A level-order traversal technique that starts from a given node and visits all its neighbors, then proceeds to the neighbors' neighbors. + +### 3.2 Depth-First Search (DFS) +DFS explores as far as possible along each branch before backtracking. + +## 4. Common Graph Algorithms + +### 4.1 Shortest Path Algorithms +- **Dijkstra’s Algorithm**: Finds the shortest path from a single source to all other vertices (for non-negative weights). +- **Bellman-Ford Algorithm**: Handles graphs with negative weights. +- **Floyd-Warshall Algorithm**: Finds the shortest paths between all pairs of vertices. + +### 4.2 Minimum Spanning Tree Algorithms +- **Prim’s Algorithm**: Greedy algorithm to find the MST, starting from any node. +- **Kruskal’s Algorithm**: Uses union-find to select the shortest edges. + +### 4.3 Topological Sorting +A linear ordering of vertices in a directed acyclic graph (DAG). + +### 4.4 Detecting Cycles +- Use DFS to detect cycles in directed/undirected graphs. + +### 4.5 Strongly Connected Components (Kosaraju’s Algorithm) +Decomposes a directed graph into strongly connected components. + +## 5. Frequently Asked Graph Problems + +### 5.1 Basic Graph Traversal +- BFS of a graph +- DFS of a graph +- Connected Components + +### 5.2 Shortest Paths +- Dijkstra’s Algorithm +- Bellman-Ford Algorithm +- Shortest Path in Binary Maze + +### 5.3 MST (Minimum Spanning Tree) +- Prim's MST +- Kruskal's MST + +### 5.4 Advanced Graph Problems +- Topological Sort of a Directed Graph +- Detect Cycle in Directed Graph +- Strongly Connected Components + +## 6. Frequently Asked DSA Graph Questions + +1. **Breadth-First Search (BFS) and Depth-First Search (DFS)** + - Implement BFS and DFS for a graph. + - Find the number of connected components in an undirected graph. + +2. **Shortest Path Algorithms** + - Find the shortest path in an unweighted graph (BFS). + - Find the shortest path in a weighted graph (Dijkstra, Bellman-Ford). + +3. **Cycle Detection** + - Detect a cycle in an undirected graph (DFS). + - Detect a cycle in a directed graph (DFS with backtracking). + +4. **Topological Sort** + - Find the topological order of vertices in a directed acyclic graph (Kahn's Algorithm or DFS-based approach). + +5. **Minimum Spanning Tree (MST)** + - Implement Prim’s algorithm. + - Implement Kruskal’s algorithm. + +6. **Strongly Connected Components** + - Find all the strongly connected components (SCCs) in a directed graph (Kosaraju’s algorithm, Tarjan’s algorithm). + +7. **Graph Coloring** + - Implement graph coloring using BFS/DFS. + - Check if a graph is bipartite. + +8. **Miscellaneous** + - Find the number of islands in a matrix (connected components problem). + - Clone a graph (deep copy of a graph). + +## 7. Common Interview Questions +1. **Leetcode 200:** Number of Islands +2. **Leetcode 207:** Course Schedule (Topological Sort) +3. **Leetcode 743:** Network Delay Time (Dijkstra) +4. **Leetcode 785:** Is Graph Bipartite? +5. **Leetcode 997:** Find the Town Judge +6. **Leetcode 399:** Evaluate Division (Graph Representation of Equations) + +-- + +## Credits + +This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. diff --git a/C++/Graphs_Basix/codes/bellman_ford.cpp b/C++/Graphs_Basix/codes/bellman_ford.cpp new file mode 100644 index 0000000..cee12e4 --- /dev/null +++ b/C++/Graphs_Basix/codes/bellman_ford.cpp @@ -0,0 +1,53 @@ +// ## Credits + +// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. + + +#include +#include + +using namespace std; + +const int INF = 1e9; // A large value representing infinity + +// Function to implement Bellman-Ford algorithm for finding the shortest path +bool bellmanFord(int start, int V, vector>& edges, vector& dist) { + dist[start] = 0; // Distance to the start node is 0 + + // Relax edges repeatedly + for (int i = 0; i < V - 1; i++) { + for (auto edge : edges) { + int u = edge[0]; // Starting node of the edge + int v = edge[1]; // Ending node of the edge + int weight = edge[2]; // Weight of the edge + + // If the current distance to u is not infinite + if (dist[u] != INF && dist[u] + weight < dist[v]) { + dist[v] = dist[u] + weight; // Update the distance to v + } + } + } + + // Check for negative-weight cycles + for (auto edge : edges) { + int u = edge[0]; + int v = edge[1]; + int weight = edge[2]; + + // If we can still relax the edge, there is a negative cycle + if (dist[u] != INF && dist[u] + weight < dist[v]) { + return false; // Negative cycle found + } + } + + return true; // No negative cycles found +} + +/* +Explanation: +- This function implements the Bellman-Ford algorithm to find the shortest paths from a starting node to all other nodes in a graph. +- Unlike Dijkstra's, it can handle negative weights and detects negative cycles. +- The algorithm relaxes all edges multiple times (V-1 times, where V is the number of vertices). +- After relaxation, it checks for negative cycles by attempting to relax the edges one more time. +- It returns a boolean indicating whether a negative cycle was detected. +*/ diff --git a/C++/Graphs_Basix/codes/bfs.cpp b/C++/Graphs_Basix/codes/bfs.cpp new file mode 100644 index 0000000..9f683b0 --- /dev/null +++ b/C++/Graphs_Basix/codes/bfs.cpp @@ -0,0 +1,45 @@ +// ## Credits + +// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. + + +#include +#include +#include + +using namespace std; + +// Function to perform Breadth-First Search (BFS) +void bfs(int start, vector>& adj) { + // Create a queue to hold nodes to visit + queue q; + // Create a visited array to keep track of visited nodes + vector visited(adj.size(), false); + + // Start the BFS from the 'start' node + q.push(start); + visited[start] = true; // Mark the start node as visited + + while (!q.empty()) { // While there are nodes to visit + int node = q.front(); // Get the front node of the queue + cout << node << " "; // Print the node (or process it) + q.pop(); // Remove the node from the queue + + // Visit all the neighbors of the current node + for (int neighbor : adj[node]) { + if (!visited[neighbor]) { // If the neighbor hasn't been visited + q.push(neighbor); // Add it to the queue for visiting + visited[neighbor] = true; // Mark it as visited + } + } + } +} + +/* +Explanation: +- This function implements Breadth-First Search (BFS) on a graph. +- It starts from a specified node (the 'start' node) and explores all of its neighboring nodes first. +- It uses a queue to keep track of nodes that need to be visited, ensuring that nodes are processed in the order they are discovered. +- A 'visited' array is used to mark nodes as visited to prevent re-visiting them, which would lead to an infinite loop. +- The function prints out each node as it is visited. +*/ diff --git a/C++/Graphs_Basix/codes/dfs.cpp b/C++/Graphs_Basix/codes/dfs.cpp new file mode 100644 index 0000000..ebe591e --- /dev/null +++ b/C++/Graphs_Basix/codes/dfs.cpp @@ -0,0 +1,37 @@ +// ## Credits + +// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. + + +#include +#include + +using namespace std; + +// Utility function for DFS +void dfsUtil(int node, vector>& adj, vector& visited) { + visited[node] = true; // Mark the current node as visited + cout << node << " "; // Print the node (or process it) + + // Visit all the neighbors of the current node + for (int neighbor : adj[node]) { + if (!visited[neighbor]) { // If the neighbor hasn't been visited + dfsUtil(neighbor, adj, visited); // Recursively visit it + } + } +} + +// Function to perform Depth-First Search (DFS) +void dfs(int start, vector>& adj) { + vector visited(adj.size(), false); // Keep track of visited nodes + dfsUtil(start, adj, visited); // Start DFS from the 'start' node +} + +/* +Explanation: +- This function performs Depth-First Search (DFS) on a graph. +- DFS explores as far as possible along each branch before backtracking, creating a path-like exploration. +- The 'dfsUtil' function is a utility that performs the actual recursion for exploring nodes. +- Similar to BFS, a 'visited' array is used to keep track of which nodes have been visited, preventing cycles. +- The function prints each node as it is visited. +*/ diff --git a/C++/Graphs_Basix/codes/dijkstra.cpp b/C++/Graphs_Basix/codes/dijkstra.cpp new file mode 100644 index 0000000..2cf7d47 --- /dev/null +++ b/C++/Graphs_Basix/codes/dijkstra.cpp @@ -0,0 +1,51 @@ +// ## Credits + +// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. + + +#include +#include +#include + +using namespace std; + +const int INF = 1e9; // A large value representing infinity + +// Function to implement Dijkstra's algorithm for finding the shortest path +vector dijkstra(int start, vector>>& graph) { + int V = graph.size(); // Number of vertices + vector dist(V, INF); // Distance array, initialized to "infinity" + dist[start] = 0; // Distance to the starting node is 0 + + // Min-heap (priority queue) to hold nodes and their distances + priority_queue, vector>, greater>> pq; + pq.push({0, start}); // Start from the initial node + + while (!pq.empty()) { // While there are nodes to process + int u = pq.top().second; // Get the node with the smallest distance + pq.pop(); // Remove it from the queue + + // Explore neighbors of the current node + for (auto& edge : graph[u]) { + int v = edge.first; // The neighboring node + int weight = edge.second; // The distance to the neighbor + + // If a shorter path to neighbor is found + if (dist[u] + weight < dist[v]) { + dist[v] = dist[u] + weight; // Update distance + pq.push({dist[v], v}); // Add neighbor to the queue + } + } + } + + return dist; // Return the distances from the start node +} + +/* +Explanation: +- This function implements Dijkstra's algorithm to find the shortest path from a starting node to all other nodes in a weighted graph. +- It uses a priority queue (min-heap) to process the next node with the smallest known distance. +- The 'dist' array keeps track of the shortest distance from the start node to every other node. +- The algorithm iteratively updates the distances to each neighboring node based on the current node's distance. +- It returns an array of the shortest distances to all nodes from the start node. +*/ diff --git a/C++/Graphs_Basix/codes/floyd_warshall.cpp b/C++/Graphs_Basix/codes/floyd_warshall.cpp new file mode 100644 index 0000000..e3b420f --- /dev/null +++ b/C++/Graphs_Basix/codes/floyd_warshall.cpp @@ -0,0 +1,88 @@ +// ## Credits + +// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. + + +#include +#include +#include + +using namespace std; + +#define INF numeric_limits::max() // Define infinity as the maximum integer value + +// Function to implement the Floyd-Warshall algorithm +void floydWarshall(int V, vector>& graph) { + // Create a distance matrix initialized with the graph values + vector> dist = graph; + + // Iterate through each vertex as an intermediate point + for (int k = 0; k < V; k++) { + // Iterate through each source vertex + for (int i = 0; i < V; i++) { + // Iterate through each destination vertex + for (int j = 0; j < V; j++) { + // Check if the path through vertex k is shorter than the current known path + if (dist[i][k] != INF && dist[k][j] != INF) { + dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]); + } + } + } + } + + // Print the shortest distance matrix + cout << "The following matrix shows the shortest distances between every pair of vertices:\n"; + for (int i = 0; i < V; i++) { + for (int j = 0; j < V; j++) { + if (dist[i][j] == INF) + cout << "INF\t"; // Print INF for unreachable paths + else + cout << dist[i][j] << "\t"; // Print the shortest distance + } + cout << endl; + } +} + +int main() { + // Number of vertices + int V = 4; + + // Define the graph as an adjacency matrix + vector> graph = { + {0, 3, INF, 5}, + {2, 0, INF, 4}, + {INF, 1, 0, INF}, + {INF, INF, 2, 0} + }; + + // Call the Floyd-Warshall algorithm + floydWarshall(V, graph); + + return 0; +} + +/* +Explanation of the Floyd-Warshall Algorithm: + +1. **Purpose**: The Floyd-Warshall algorithm is used to find the shortest paths between all pairs of vertices in a weighted graph. It can handle negative weights but not negative cycles (where the total weight becomes negative). + +2. **Input**: The algorithm takes in a graph represented as an adjacency matrix. Each element `graph[i][j]` represents the weight of the edge from vertex `i` to vertex `j`. If there is no edge, the value is set to `INF` (infinity), which signifies that there is no direct path between the two vertices. + +3. **Distance Matrix**: We create a distance matrix, `dist`, which initially is the same as the input graph. It will be updated to reflect the shortest distances between each pair of vertices. + +4. **Main Idea**: The algorithm uses a three-level nested loop: + - The outer loop iterates over each vertex `k`, which acts as an intermediate point for checking paths. + - The middle loop iterates over each source vertex `i`. + - The innermost loop iterates over each destination vertex `j`. + - For each pair of vertices `i` and `j`, the algorithm checks if the path from `i` to `j` through `k` is shorter than the currently known shortest path from `i` to `j`. If it is, we update the distance matrix with this new shorter distance. + +5. **Updating Distances**: The line `dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);` performs the check and update. It only updates the distance if both `dist[i][k]` and `dist[k][j]` are not `INF`, which means both paths are reachable. + +6. **Output**: After processing all vertices, the algorithm prints the resulting distance matrix, showing the shortest distances between each pair of vertices. If the distance is `INF`, it indicates that there is no path between those two vertices. + +7. **Time Complexity**: The time complexity of the Floyd-Warshall algorithm is O(V^3), where V is the number of vertices. This is because of the three nested loops, each iterating through all vertices. + +8. **Use Cases**: This algorithm is widely used in applications such as network routing, urban transportation systems, and game development, where determining the shortest path between points is necessary. + +By following these steps, the Floyd-Warshall algorithm efficiently computes the shortest paths in a graph. +*/ diff --git a/C++/Graphs_Basix/codes/kruskal.cpp b/C++/Graphs_Basix/codes/kruskal.cpp new file mode 100644 index 0000000..89d2470 --- /dev/null +++ b/C++/Graphs_Basix/codes/kruskal.cpp @@ -0,0 +1,71 @@ +// ## Credits + +// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. + + +#include +#include +#include + +using namespace std; + +// Structure to represent an edge +struct Edge { + int u, v, weight; +}; + +// Find function for Union-Find +int find(int node, vector& parent) { + if (parent[node] != node) { + parent[node] = find(parent[node], parent); // Path compression + } + return parent[node]; +} + +// Union function for Union-Find +void unionNodes(int u, int v, vector& parent, vector& rank) { + int rootU = find(u, parent); + int rootV = find(v, parent); + + // Union by rank + if (rootU != rootV) { + if (rank[rootU] < rank[rootV]) { + parent[rootU] = rootV; + } else if (rank[rootU] > rank[rootV]) { + parent[rootV] = rootU; + } else { + parent[rootV] = rootU; + rank[rootU]++; + } + } +} + +// Function to implement Kruskal's algorithm for finding Minimum Spanning Tree (MST) +int kruskal(vector& edges, int V) { + sort(edges.begin(), edges.end(), [](Edge a, Edge b) { + return a.weight < b.weight; // Sort edges by weight + }); + + vector parent(V), rank(V, 0); + for (int i = 0; i < V; i++) parent[i] = i; // Initialize Union-Find + + int mstWeight = 0; // Total weight of the MST + + for (Edge edge : edges) { + if (find(edge.u, parent) != find(edge.v, parent)) { // If u and v are not connected + unionNodes(edge.u, edge.v, parent, rank); // Union the sets + mstWeight += edge.weight; // Add edge weight to total + } + } + + return mstWeight; // Return the total weight of the MST +} + +/* +Explanation: +- This function implements Kruskal's algorithm to find the Minimum Spanning Tree (MST) of a graph. +- The MST connects all vertices with the minimum total edge weight without forming any cycles. +- It uses a Union-Find data structure to manage and merge disjoint sets of nodes. +- The edges are sorted by weight to ensure that the smallest edges are considered first. +- The function returns the total weight of the MST. +*/ diff --git a/C++/Graphs_Basix/codes/prims.cpp b/C++/Graphs_Basix/codes/prims.cpp new file mode 100644 index 0000000..18b4cd8 --- /dev/null +++ b/C++/Graphs_Basix/codes/prims.cpp @@ -0,0 +1,66 @@ + +// ## Credits + +// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. + + +#include +#include +#include + +using namespace std; + +// Struct to represent an edge in the graph +struct Edge { + int u, v, weight; // vertices u and v and the weight of the edge +}; + +// Function to compare two edges based on their weight +bool compare(Edge a, Edge b) { + return a.weight < b.weight; // return true if weight of edge a is less than edge b +} + +// Function to find the root of the set that contains vertex v +int findSet(int v, vector& parent) { + if (v == parent[v]) // if v is its own parent + return v; // return v as the root + // Path compression: update the parent of v to the root + return parent[v] = findSet(parent[v], parent); +} + +// Function to unite two sets containing vertices a and b +void unionSets(int a, int b, vector& parent, vector& rank) { + a = findSet(a, parent); // find the root of set containing a + b = findSet(b, parent); // find the root of set containing b + if (a != b) { // if a and b are in different sets + // Union by rank: attach the tree with a smaller rank under the root of the tree with a larger rank + if (rank[a] < rank[b]) + swap(a, b); // ensure a is the root with greater rank + parent[b] = a; // make b's root point to a's root + // If the ranks are equal, increase the rank of the new root + if (rank[a] == rank[b]) + rank[a]++; + } +} + +// Function implementing Kruskal's algorithm to find the weight of the Minimum Spanning Tree (MST) +int kruskal(int V, vector& edges) { + vector parent(V), rank(V, 0); // create parent and rank vectors + for (int i = 0; i < V; i++) + parent[i] = i; // initialize each vertex to be its own parent + + sort(edges.begin(), edges.end(), compare); // sort edges by weight + int mstWeight = 0; // variable to store the total weight of the MST + + // Iterate over sorted edges + for (Edge e : edges) { + // Check if the vertices u and v of the edge belong to different sets + if (findSet(e.u, parent) != findSet(e.v, parent)) { + mstWeight += e.weight; // add the weight of the edge to mstWeight + unionSets(e.u, e.v, parent, rank); // unite the sets containing u and v + } + } + + return mstWeight; // return the total weight of the MST +} + diff --git a/C++/Graphs_Basix/codes/topological_sort.cpp b/C++/Graphs_Basix/codes/topological_sort.cpp new file mode 100644 index 0000000..b2df9a1 --- /dev/null +++ b/C++/Graphs_Basix/codes/topological_sort.cpp @@ -0,0 +1,52 @@ +// ## Credits + +// This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated. + + +#include +#include +#include + +using namespace std; + +// Function to perform DFS for topological sorting +void topologicalSortUtil(int node, vector>& adj, vector& visited, stack& Stack) { + visited[node] = true; // Mark the current node as visited + + // Visit all the neighbors of the current node + for (int neighbor : adj[node]) { + if (!visited[neighbor]) { + topologicalSortUtil(neighbor, adj, visited, Stack); // Recur for unvisited neighbors + } + } + + Stack.push(node); // Push the current node to the stack after visiting all its neighbors +} + +// Function to perform topological sorting on a directed graph +void topologicalSort(vector>& adj) { + stack Stack; // Stack to hold the topological order + vector visited(adj.size(), false); // Keep track of visited nodes + + // Call the recursive helper function for each node + for (int i = 0; i < adj.size(); i++) { + if (!visited[i]) { + topologicalSortUtil(i, adj, visited, Stack); // Start DFS + } + } + + // Print the topological order + while (!Stack.empty()) { + cout << Stack.top() << " "; // Print the nodes in topological order + Stack.pop(); // Remove the node from the stack + } +} + +/* +Explanation: +- This function implements topological sorting for a directed acyclic graph (DAG). +- Topological sorting orders the nodes such that for every directed edge (u, v), node u comes before node v. +- It uses a stack to store the order of nodes as they are finished processing. +- A visited array is used to avoid processing a node more than once. +- After finishing all nodes, it prints the nodes in topological order by popping them from the stack. +*/ diff --git a/C++/Graphs_Basix/question.md b/C++/Graphs_Basix/question.md new file mode 100644 index 0000000..7957f05 --- /dev/null +++ b/C++/Graphs_Basix/question.md @@ -0,0 +1,9 @@ +# Problem Statement + +Graphs are an essential data structure in computer science, commonly used to model relationships between objects. They play a significant role in various domains such as social networks, transportation systems, and computer networks. However, many students and professionals struggle to understand the intricate concepts and algorithms associated with graphs due to their complexity and diverse applications. + +To address this challenge, there is a need for a comprehensive cheat sheet that consolidates the fundamental theory, common algorithms, and frequently asked questions related to graph data structures. This cheat sheet aims to serve as a quick reference guide, helping learners reinforce their understanding of graphs, enabling efficient problem-solving, and preparing for interviews and exams. By having all the essential information in one place, individuals can enhance their knowledge and confidence in working with graphs in real-world applications. + +## Credits + +This cheat sheet was created by [Mayur Nimkande](https://github.com/Mayur-nimkande-20), whose contributions are greatly appreciated.