Queries to find the count of connected Non-Empty Cells in a Matrix with updates

Given a boolean matrix mat[][] consisting of N rows and M columns, initially filled with 0‘s(empty cells), an integer K and queries Q[][] of the type {X, Y}, the task is to replace mat[X][Y] = 1(non-empty cells) and count the number of connected non-empty cells from the given matrix.
Examples: 
 

Input: N = 3, M = 3, K = 4, Q[][] = {{0, 0}, {1, 1}, {1, 0}, {1, 2}} 
Output: 1 2 1 1 
Explanation: 
Initially, mat[][] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}} 
Query 1: mat[][] = {{1, 0, 0}, {0, 0, 0}, {0, 0, 0}}, Count = 1 
Query 1: mat[][] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 0}}, Count = 2 
Query 1: mat[][] = {{1, 0, 0}, {1, 1, 0}, {0, 0, 0}}, Count = 1 
Query 1: mat[][] = {{1, 0, 0}, {1, 1, 1}, {0, 0, 0}}, Count = 1
Input: N = 2, M = 2, K = 2, Q[][] = {{0, 0}, {0, 1}} 
Output : 1 1 
 

Approach: 
The problem can be solved using Disjoint Set Data Structure. Follow the steps below to solve the problem: 
 

  • Since, initially there is no 1‘s in the matrix, count = 0.
  • Transform the two dimension problem into the classic Union-find, by perform a linear mapping index = X * M + Y, where M is the column length.
  • After setting an index in each query, increment count.
  • If a non-empty cell is present in any of the 4 adjacent cells: 
    • Perform Union opertion for current index and adjacent cell(connecting two Sets).
    • Decrement count as two Sets are connected.

Below is the implementation of the above approach:

C++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
  
// Count of connected cells
int ctr = 0;
  
// Function to return the representative
// of the Set to which x belongs
int find(vector<int>& parent, int x)
{
  
    // If x is parent of itself
    if (parent[x] == x)
  
        // x is representative
        // of the Set
        return x;
  
    // Otherwise
    parent[x] = find(parent, parent[x]);
  
    // Path Compression
    return parent[x];
}
  
// Unites the set that includes
// x and the set that includes y
void setUnion(vector<int>& parent,
              vector<int>& rank, int x, int y)
{
    // Find the representatives(or the
    // root nodes) for x an y
    int parentx = find(parent, x);
    int parenty = find(parent, y);
  
    // If both are in the same set
    if (parenty == parentx)
        return;
  
    // Decrement count
    ctr--;
  
    // If x's rank is less than y's rank
    if (rank[parentx] < rank[parenty]) {
        parent[parentx] = parenty;
    }
  
    // Otherwise
    else if (rank[parentx] > rank[parenty]) {
        parent[parenty] = parentx;
    }
    else {
  
        // Then move x under y (doesn't matter
        // which one goes where)
        parent[parentx] = parenty;
  
        // And increment the result tree's
        // rank by 1
        rank[parenty]++;
    }
}
  
// Function to count the number of
// connected cells in the matrix
vector<int> solve(int n, int m,
                  vector<pair<int, int> >& query)
{
  
    // Store result for queries
    vector<int> result(query.size());
  
    // Store representative of
    // each element
    vector<int> parent(n * m);
  
    // Initially, all elements
    // are in their own set
    for (int i = 0; i < n * m; i++)
        parent[i] = i;
  
    // Stores the rank(depth) of each node
    vector<int> rank(n * m, 1);
  
    vector<bool> grid(n * m, 0);
  
    for (int i = 0; i < query.size(); i++) {
  
        int x = query[i].first;
        int y = query[i].second;
  
        // If the grid[x*m + y] is already
        // set, store the result
        if (grid[m * x + y] == 1) {
            result[i] = ctr;
            continue;
        }
  
        // Set grid[x*m + y] to 1
        grid[m * x + y] = 1;
  
        // Increment count.
        ctr++;
  
        // Check for all adjacent cells
        // to do a Union with neighbour's
        // set if neighbour is also 1
        if (x > 0 and grid[m * (x - 1) + y] == 1)
            setUnion(parent, rank,
                     m * x + y, m * (x - 1) + y);
  
        if (y > 0 and grid[m * (x) + y - 1] == 1)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y - 1);
  
        if (x < n - 1 and grid[m * (x + 1) + y] == 1)
            setUnion(parent, rank,
                     m * x + y, m * (x + 1) + y);
  
        if (y < m - 1 and grid[m * (x) + y + 1] == 1)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y + 1);
  
        // Store result.
        result[i] = ctr;
    }
    return result;
}
  
// Driver Code
int main()
{
    int N = 3, M = 3, K = 4;
  
    vector<pair<int, int> > query
        = { { 0, 0 },
            { 1, 1 },
            { 1, 0 },
            { 1, 2 } };
    vector<int> result = solve(N, M, query);
  
    for (int i = 0; i < K; i++)
        cout << result[i] << " ";
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to implement
// the above approach
import java.util.*;
  
class GFG{
  
// Count of connected cells
static int ctr = 0;
  
// Function to return the representative
// of the Set to which x belongs
static int find(int []parent, int x)
{
      
    // If x is parent of itself
    if (parent[x] == x)
  
        // x is representative
        // of the Set
        return x;
  
    // Otherwise
    parent[x] = find(parent, parent[x]);
  
    // Path Compression
    return parent[x];
}
  
// Unites the set that includes
// x and the set that includes y
static void setUnion(int[] parent,
                     int[] rank, int x, int y)
{
      
    // Find the representatives(or the
    // root nodes) for x an y
    int parentx = find(parent, x);
    int parenty = find(parent, y);
  
    // If both are in the same set
    if (parenty == parentx)
        return;
  
    // Decrement count
    ctr--;
  
    // If x's rank is less than y's rank
    if (rank[parentx] < rank[parenty])
    {
        parent[parentx] = parenty;
    }
  
    // Otherwise
    else if (rank[parentx] > rank[parenty])
    {
        parent[parenty] = parentx;
    }
    else 
    {
          
        // Then move x under y (doesn't matter
        // which one goes where)
        parent[parentx] = parenty;
  
        // And increment the result tree's
        // rank by 1
        rank[parenty]++;
    }
}
  
// Function to count the number of
// connected cells in the matrix
static int [] solve(int n, int m,
                    int [][]query)
{
      
    // Store result for queries
    int []result = new int[query.length];
      
    // Store representative of
    // each element
    int []parent = new int[n * m];
  
    // Initially, all elements
    // are in their own set
    for(int i = 0; i < n * m; i++)
        parent[i] = i;
  
    // Stores the rank(depth) of each node
    int []rank = new int[n * m];
    Arrays.fill(rank, 1);
      
    boolean []grid = new boolean[n * m];
  
    for(int i = 0; i < query.length; i++)
    {
        int x = query[i][0];
        int y = query[i][1];
  
        // If the grid[x*m + y] is already
        // set, store the result
        if (grid[m * x + y] == true)
        {
            result[i] = ctr;
            continue;
        }
  
        // Set grid[x*m + y] to 1
        grid[m * x + y] = true;
  
        // Increment count.
        ctr++;
  
        // Check for all adjacent cells
        // to do a Union with neighbour's
        // set if neighbour is also 1
        if (x > 0 && grid[m * (x - 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x - 1) + y);
  
        if (y > 0 && grid[m * (x) + y - 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y - 1);
  
        if (x < n - 1 && grid[m * (x + 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x + 1) + y);
  
        if (y < m - 1 && grid[m * (x) + y + 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y + 1);
  
        // Store result.
        result[i] = ctr;
    }
    return result;
}
  
// Driver Code
public static void main(String[] args)
{
    int N = 3, M = 3, K = 4;
  
    int [][]query = { { 0, 0 },
                      { 1, 1 },
                      { 1, 0 },
                      { 1, 2 } };
    int[] result = solve(N, M, query);
  
    for(int i = 0; i < K; i++)
        System.out.print(result[i] + " ");
}
}
  
// This code is contributed by Amit Katiyar

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to implement
// the above approach
using System;
class GFG{
  
// Count of connected cells
static int ctr = 0;
  
// Function to return the representative
// of the Set to which x belongs
static int find(int []parent, int x)
{
      
    // If x is parent of itself
    if (parent[x] == x)
  
        // x is representative
        // of the Set
        return x;
  
    // Otherwise
    parent[x] = find(parent, parent[x]);
  
    // Path Compression
    return parent[x];
}
  
// Unites the set that includes
// x and the set that includes y
static void setUnion(int[] parent,
                     int[] rank, 
                     int x, int y)
{
      
    // Find the representatives(or the
    // root nodes) for x an y
    int parentx = find(parent, x);
    int parenty = find(parent, y);
  
    // If both are in the same set
    if (parenty == parentx)
        return;
  
    // Decrement count
    ctr--;
  
    // If x's rank is less than y's rank
    if (rank[parentx] < rank[parenty])
    {
        parent[parentx] = parenty;
    }
  
    // Otherwise
    else if (rank[parentx] > rank[parenty])
    {
        parent[parenty] = parentx;
    }
    else
    {
          
        // Then move x under y (doesn't matter
        // which one goes where)
        parent[parentx] = parenty;
  
        // And increment the result tree's
        // rank by 1
        rank[parenty]++;
    }
}
  
// Function to count the number of
// connected cells in the matrix
static int [] solve(int n, int m,
                    int [,]query)
{
      
    // Store result for queries
    int []result = new int[query.Length];
      
    // Store representative of
    // each element
    int []parent = new int[n * m];
  
    // Initially, all elements
    // are in their own set
    for(int i = 0; i < n * m; i++)
        parent[i] = i;
  
    // Stores the rank(depth) of each node
    int []rank = new int[n * m];
    for(int i = 0; i < rank.Length; i++)
        rank[i] = 1;
    bool []grid = new bool[n * m];
  
    for(int i = 0; i < query.GetLength(0); i++)
    {
        int x = query[i, 0];
        int y = query[i, 1];
  
        // If the grid[x*m + y] is already
        // set, store the result
        if (grid[m * x + y] == true)
        {
            result[i] = ctr;
            continue;
        }
  
        // Set grid[x*m + y] to 1
        grid[m * x + y] = true;
  
        // Increment count.
        ctr++;
  
        // Check for all adjacent cells
        // to do a Union with neighbour's
        // set if neighbour is also 1
        if (x > 0 && grid[m * (x - 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x - 1) + y);
  
        if (y > 0 && grid[m * (x) + y - 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y - 1);
  
        if (x < n - 1 && grid[m * (x + 1) + y] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x + 1) + y);
  
        if (y < m - 1 && grid[m * (x) + y + 1] == true)
            setUnion(parent, rank,
                     m * x + y, m * (x) + y + 1);
  
        // Store result.
        result[i] = ctr;
    }
    return result;
}
  
// Driver Code
public static void Main(String[] args)
{
    int N = 3, M = 3, K = 4;
  
    int [,]query = {{ 0, 0 }, { 1, 1 },
                    { 1, 0 }, { 1, 2 }};
    int[] result = solve(N, M, query);
  
    for(int i = 0; i < K; i++)
        Console.Write(result[i] + " ");
}
}
  
// This code is contributed by sapnasingh4991

chevron_right


Output: 

1 2 1 1

 

Time Complexity: O(N * M * sizeof(Q)) 
Auxiliary Space: O(N*M)
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.




My Personal Notes arrow_drop_up

Recommended Posts:


Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.