✅✅Graph - Summary ✅✅

Types of Graph Problems:

  1. DFS Depth First Search
    • 2D Matrix
    • Pure Graph
  2. BFS Breadth First Search
    • 2D Matrix
    • Pure Graph
  3. Topological Sort
    • Directed Acyclic Graph
    • Undirected Graph : Cant use on undirected graph as each edge forms a cycle
  4. Cycle Detection
    • Undirected Graph
      • BFS
      • DFS
    • Directed Graph
      • BFS
      • DFS
  5. UnionFind
  6. Shortest Path
    • Shortest Path in Directed Acyclic Graph
    • Dijkstra Fails when negative weight cycle
    • Bellman Ford Detects negative weight cycle
    • Floyd Warshall
  7. Minimum Spanning Tree
    • Prims
    • Kruskal
  8. Bipartite Graph

⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

1. 💎DFS/BFS on 2D-Matrix

ProblemRemark
547. Number of ProvincesDFS/ BFS , Input is AdjMatrix
200. Number of IslandsDFS/ BFS
733. Flood FillDFS/ BFS
463. Island PerimeterDFS/BFS
417. Pacific Atlantic Water FlowBFS/DFS
1034. Coloring A BorderDFS/BFS We are given a vertex of a connected component ,and we need to color its boundary .
1254. Number of Closed IslandsDFS/BFS Can be converted to LC 200
695. Max Area Of islandDFS/BFS
1219. Path with Maximum GoldDFS/BFS + BACKTRACKING
733. Flood Fill
DFS
class Solution {
public:
    void dfs(vector<vector<int>>& image, int i, int j,int val, int newColor)
    {
        if(i<0 || i>=image.size() || j<0 || j>= image[0].size() || image[i][j] == newColor || image[i][j] != val)
        {
            return;
        }
        image[i][j] = newColor;
        dfs(image,i-1,j,val,newColor);
        dfs(image,i+1,j,val,newColor);
        dfs(image,i,j-1,val,newColor);
        dfs(image,i,j+1,val,newColor);
    }
    
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor)
    {
        int val = image[sr][sc];
        dfs(image,sr,sc,val,newColor);
        return image;
    }
};

BFS

class Solution {
public:
   
    vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int newColor)
    {
        // vector<vector<bool>> isPainted(image.size(), vector<bool>(image[0].size(), false));
        int oldColor=image[sr][sc];
        if(oldColor == newColor) return image;
        
        queue<pair<int,int>> q;
        int m= image.size();
        int n=image[0].size();
       
        q.push({sr,sc});
        // isPainted[sr][sc]=true;
        image[sr][sc]=newColor;
         int dir[4][2]={{0,1},{1,0},{-1,0},{0,-1}}; // up  
        
        
        while(q.empty()==false)
        {
            int currx=q.front().first;
            int curry=q.front().second;
            
            q.pop();
            
            // explore all directions
            for(int i=0 ; i<=3;i++)
            {       int nx= currx+dir[i][0];
                    int ny =curry+dir[i][1];
                if(nx>=0 && ny >= 0 && nx <m  && ny<n && image[nx][ny]==oldColor )
                {
                  
                    image[nx][ny]=newColor;
                    q.push({nx,ny});
                }
            }
           
        }
        return image;
    }
};
200. Number of Islands
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        int m = grid.size();
        int n = grid[0].size();

        int count = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == '1') {
                    // dfs(grid,i,j);
                    bfs(grid, i, j);
                    count++;
                }
            }
        }
        return count;
    }

    void dfs(vector<vector<char>>& grid, int i, int j) {

        if (i < 0 || j < 0 || i >= grid.size() || j >= grid[0].size() || grid[i][j] != '1')
            return;

        grid[i][j] = '0';

        dfs(grid, i + 1, j);
        dfs(grid, i - 1, j);
        dfs(grid, i, j + 1);
        dfs(grid, i, j - 1);
    }

    void bfs(vector<vector<char>>& grid, int i, int j) {
        queue<pair<int, int>> q;
        q.push({i, j});
        int dx[] = {1, -1, 0, 0};
        int dy[] = {0, 0, 1, -1};
        while (q.empty() == false) {
            auto [r, c] = q.front();
            q.pop();

            // mark grid visited
            grid[i][j] = 'x';

            for (int k = 0; k < 4; k++) {
                int row_dash = r + dx[k];
                int col_dash = c + dy[k];
                if (row_dash >= 0 && col_dash >= 0 && row_dash < grid.size() &&
                    col_dash < grid[0].size() && grid[row_dash][col_dash] == '1') {
                    grid[row_dash][col_dash] = 'x';
                    q.push({row_dash, col_dash});
                }
            }
        }
    }
};
463. Island Perimeter
class Solution {
public:
    int m, n;
    int islandPerimeter(vector<vector<int>>& grid) {
        m = grid.size();
        n = grid[0].size();
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    return dfs(grid, i, j);
                }
            }
        }
        return 0;
    }
    int dfs(vector<vector<int>>& grid, int i, int j) {
        // stores the count of edges of this block + its neighbours

        if (i < 0 || i > m - 1 || j < 0 || j > n - 1)
            return 1;
        if (grid[i][j] == -1)
            return 0;
        if (grid[i][j] == 0)
            return 1;

        grid[i][j] = -1;
        int count = 0;
        // Now we have counted the edges for current cell we proceed for dfs
        count += dfs(grid, i - 1, j);
        count += dfs(grid, i + 1, j);
        count += dfs(grid, i, j - 1);
        count += dfs(grid, i, j + 1);
        return count;
    }
};
695. Max Area of Island
class Solution {
public:
    int m, n;
    int maxAreaOfIsland(vector<vector<int>>& grid) {
        m = grid.size();
        n = grid[0].size();
        int ans = 0;
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                if (grid[i][j] == 1) {
                    int area = dfs(grid, i, j); // dfs will calculate area
                    ans = max(ans, area);
                }
            }
        }
        return ans;
    }

    int dfs(vector<vector<int>>& grid, int i, int j) {
        // safety check
        if (i < 0 || j < 0 || i > m - 1 || j > n - 1 || grid[i][j] == 0)
            return 0;
        grid[i][j] = 0;
        int left = dfs(grid, i - 1, j);
        int right = dfs(grid, i + 1, j);
        int up = dfs(grid, i, j - 1);
        int down = dfs(grid, i, j + 1);

        return 1 + left + right + up + down;
    }
};
1254. Number of Closed Island
DFS
class Solution {
public:
    int m, n;
    int closedIsland(vector<vector<int>>& grid) {
        m = grid.size();
        n = grid[0].size();
        int count = 0;
        for (int i = 0; i < m ; i++) {
            for (int j = 0; j < n ; j++) {
                if (grid[i][j] == 0) {
                    if (dfs(grid, i, j) == true)
                        count++;
                }
            }
        }
        return count;
    }

    bool dfs(vector<vector<int>>& grid, int i, int j) {
        // if boundary crossed return false as island not closed
        if (i == -1 || j == -1 || i == m  || j == n )
            return false;
        if (grid[i][j]==1)
            return true;
        grid[i][j] = 1;
        bool left = dfs(grid, i - 1, j);
        bool right = dfs(grid, i + 1, j);
        bool up = dfs(grid, i, j - 1);
        bool down = dfs(grid, i, j + 1);

        return left && right && up && down;
    }
};
1034. Coloring a Border
class Solution {
public:
    int m, n;
    vector<vector<int>> colorBorder(vector<vector<int>>& image, int sr, int sc,int color) {
        m = image.size();
        n = image[0].size();
        vector<vector<bool>> vis(m, vector<bool>(n, false));//
        int hunt = image[sr][sc];
        dfs(sr, sc, image, vis, hunt, color);
        return image;
    }
    void dfs(int i, int j, vector<vector<int>>& image,vector<vector<bool>>& vis, int curr_color, int color){

        if (i < 0 || j < 0 || i >= m || j >= n || vis[i][j] || image[i][j] != curr_color)
            return;

        vis[i][j] = true;
		//check if boundary then color the curr node
        if (i == 0 || j == 0 || i >= m - 1 || j >= n - 1) 
            image[i][j] = color;
        
        if ((i + 1 <= m - 1 && image[i + 1][j] != curr_color && !vis[i + 1][j]) ||
            (i - 1 >= 0 && image[i - 1][j] != curr_color && !vis[i - 1][j]) ||
            (j + 1 <= n - 1 && image[i][j + 1] != curr_color && !vis[i][j + 1]) ||
            (j - 1 >= 0 && image[i][j - 1] != curr_color && !vis[i][j - 1]))
            image[i][j] = color;
        dfs(i + 1, j, image, vis, curr_color, color);
        dfs(i - 1, j, image, vis, curr_color, color);
        dfs(i, j + 1, image, vis, curr_color, color);
        dfs(i, j - 1, image, vis, curr_color, color);
    }
};

2. BFS Supremacy- (BFS OVER DFS on 2-D GRID Problems)

ProblemRemark
09. Snakes and LaddersDFS Approach would work perfectly fine if the graph is acylic but here the graph could be cyclic as well.
1091. Shortest Path in Binary MatrixDFS Gives TLE , BFS runs perfectly
1162. As Far from Land as PossibleMulti source BFS from land cells
542. 01 Matrixdistance of the nearest 0 for each cell. hence BFS
994. Rotting OrangesBFS Better than DFS
2812. Find the Safest Path in a GridBFS + Binary Search on Answer

BFS on Strings

752. Open the Lock
433. Minimum Genetic Mutation
Up next:
130. Surrounded Regions
1559. Detect Cycle in 2d grid
2596. Check Knight Tour Configuration


Pure Graph Problems with Edges given

Graph Creation from Edges
We create the graph first in these type of problems we can use a

2D- Vector vector<vector>graph(n);
Vector of arrays vectoradj[n];

unorderedMap with vertex as key and its neighbours as value store in vector
unordered_map<int,vector>mp

  1. For Directed Graph
vector<int>adj[n];
 for(int i=0;i<mat.size();i++){
            adj[mat[i][1]].push_back(mat[i][0]);
        }
  1. For Undirected Graph
vector<int>adj[n];
 for(int i=0;i<mat.size();i++){
            adj[ mat[i][1] ].push_back(mat[i][0]);
			adj[ mat[i][0] ].push_back(mat[i][1]);
        }

3. 💎Topological Sorting

Topological sort
/*LC 207 Course Schedule 
edges given as dependency of courses 
Return true if you can finish all courses. Otherwise, return false.*/
class Solution {
public:
    bool canFinish(int numCourses, vector<vector<int>>& mat) {
        int n = numCourses;
        vector<int> adj[n];
        vector<int> indegree(n, 0);
        for (int i = 0; i < mat.size(); i++) {
            adj[mat[i][1]].push_back(mat[i][0]);
            indegree[mat[i][0]]++;
        }
        vector<int> visited;
        queue<int> q;
        for (int i = 0; i < n; i++) {
            if (indegree[i] == 0) {
                q.push(i);
                visited.push_back(i);
            }
        }
        while (q.empty() == false) {
            int x = q.front();
            q.pop();
            for (auto it : adj[x]) {
                if (--indegree[it] == 0) {
                    q.push(it);
                    visited.push_back(it);
                }
            }
        }
        if (visited.size() != n)
            return false;
        else
            return true;
    }
};

Course Schedule : https://leetcode.com/problems/course-schedule/
Course Schedule II: https://leetcode.com/problems/course-schedule-ii/
Sequence Reconstruction: https://leetcode.com/problems/sequence-reconstruction/
Alien Dictionary: https://leetcode.com/problems/alien-dictionary/solution/

4. Cycle Detection

Detect cycle Undirected Graph DFS
class Solution {
  private:
    bool dfs(int src , int parent , vector<int>adj[],vector<int>&vis){
        vis[src]=1;
        for(auto it : adj[src]){
            if(vis[it]==-1){
               if( dfs(it,src,adj,vis))
                return true;
            }
            else if(it!=parent)// vis[it]==1
                return true;
        }
        return false;// will reach here if no cycle found
    }
  public:
    // Function to detect cycle in an undirected graph.
    bool isCycle(int V, vector<int> adj[]) {
        // Code here
        vector<int>vis(V,-1);
        
        for(int i=0;i<V;i++){
            if(vis[i]==-1 && dfs(i,-1,adj,vis))
                return true;//cycle found
        }
        return false;
    }
};
Detect cycle Undirected Graph BFS
class Solution {
  public:
    // Function to detect cycle in an undirected graph.
    // bass neighbour parent na ho warna diqqat ho skti hai
    
    bool bfs(int src, vector<int> adj[] , vector<int>&vis)
    {
        
      queue<pair<int,int>>q;
      vis[src]=1;
      q.push({src,-1});
      
      while(!q.empty()){
          int node=q.front().first;
          int parent=q.front().second;
          q.pop();
          
          for(auto it:adj[node]){
              if(vis[it]==0){
                  vis[it]=1;
                  q.push({it,node});
              }
              else if(it!=parent)
                  return true;
          }
      }
      return false;
    }
    
    
    bool isCycle(int V, vector<int> adj[]) {
        // Code here
        vector<int>vis(V,0);
        for(int i=0;i<V;i++){
            if(vis[i]==0){
                if(bfs(i,adj,vis))
                    return true; // cycle found
            }
        }
        return false;
    }
};

https://leetcode.com/problems/find-eventual-safe-states/

5. Union Find

6. Shortest Path

Dijkstra Algorithm
class Solution
{
	public:
	//Function to find the shortest distance of all the vertices
    //from the source vertex S.
    typedef pair<int,int> P;
    vector <int> dijkstra(int V, vector<vector<int>> adj[], int S) {
        vector<int>vis(V,false);
        vector<int>dist(V,1e9);
        dist[S]=0;
        priority_queue<P,vector<P>,greater<P>>pq;//{cost,node}
        pq.push({0,S});
        while(!pq.empty()){
            int cost=pq.top().first;
            int u=pq.top().second;
            pq.pop();
            vis[u]=true;
            for(auto &it: adj[u]){
                int v=it[0];
                int w=it[1];
                if(vis[v]==false && dist[v]>dist[u]+w){
                    dist[v]=dist[u]+w;
                    pq.push({dist[v],v}); 
                }
            }
        }
        return dist;
    }
};
Bellman-Ford Algorithm Given a weighted and directed graph of V vertices and E edges, Find the shortest distance of all the vertex's from the source vertex S. If a vertices can't be reach from the S then mark the distance as 10^8. Note: If the Graph contains a negative cycle then return an array consisting of only -1.
class Solution {
  public:
    /*  Function to implement Bellman Ford
    *   edges: vector of vectors which represents the graph
    *   S: source vertex to start traversing graph with
    *   V: number of vertices
    */
    vector<int> bellman_ford(int V, vector<vector<int>>& edges, int S) {
        // Code here
        vector<int>dist(V,1e8);
        dist[S]=0;
        for(int i=0;i<V-1;i++){
            for(auto &e : edges){
                int node=e[0];
                int adjNode=e[1];
                int wt=e[2];
                if(dist[node]!=1e8 && dist[node]+wt<dist[adjNode]){
                    dist[adjNode]=dist[node]+wt;
                }
            }
        }
        //check -ve cycle
        for(auto&e:edges){
            int node=e[0];
            int adjNode=e[1];
            int wt=e[2];
            if(dist[node]!=1e8 && dist[node]+wt<dist[adjNode] )
                return {-1};
        }
        return dist;
        
    }
};

https://leetcode.com/problems/network-delay-time/
https://leetcode.com/problems/cheapest-flights-within-k-stops/ BFS(queue) / Bellman Ford for k+1 iterations
https://leetcode.com/problems/number-of-ways-to-arrive-at-destination/

7. Spanning Tree

PRIMS ALGORITHM
class Solution {
public:
    // Function to find sum of weights of edges of the Minimum Spanning Tree.
    int spanningTree(int V, vector<vector<int>> adj[]) {
        vector<bool> visited(V, false); 
        vector<int> cost(V, INT_MAX);  // current minimum cost
        cost[0] = 0;
        priority_queue<pair<int, int>, vector<pair<int, int>>,
                       greater<pair<int, int>>>
            pq;
        pq.push({cost[0], 0});
        int ans = 0;
        while (pq.empty() == false) {
            auto x = pq.top();
            int u = x.second;
            pq.pop();
            if (visited[u] == true)
                continue;
            visited[u] = true;
            ans = ans + x.first;
            for (auto it : adj[u]) {
                int v = it[0];
                int w = it[1];
                if (visited[v] == false && w < cost[v]) {
                    cost[v] = w;
                    pq.push({cost[v], v});
                }
            }
        }

        return ans;
    }
};

https://leetcode.com/problems/min-cost-to-connect-all-points
https://leetcode.com/problems/connecting-cities-with-minimum-cost [Locked]CN

8. Biparite

...TO BE CONTINUED
DSU
Floyd warshall
Kosoraju
Kahn
Bipartite

9 Tree

Problems where we need to update the inut tree in sopme graph
https://leetcode.com/problems/all-nodes-distance-k-in-binary-tree/

Other Great Graph Summary Links

Graph Algorithms
Graph : Bipartite , Topological sort , kahns algo
Graph Patterns : Union Find , DFS , BFS , Graph coloring ,Topological ,Shortest Path

Comments (0)