Wednesday, 25 July 2012

Given a 2–d matrix , which has only 1’s and 0’s in it. Find the total number of connected sets in that matrix.



Explanation:
Connected set can be defined as group of cell(s) which has 1 mentioned on it and have at least one other cell in that set with which they share the neighbor relationship. A cell with 1 in it and no surrounding neighbor having 1 in it can be considered as a set with one cell in it. Neighbors can be defined as all the cells adjacent to the given cell in 8 possible directions ( i.e N , W , E , S , NE , NW , SE , SW direction ). A cell is not a neighbor of itself.


Input format :

First line of the input contains T , number of test-cases.
Then follow T testcases. Each testcase has given format.
N [ representing the dimension of the matrix N X N ].
Followed by N lines , with N numbers on each line.



Ouput format :

For each test case print one line ,  number of connected component it has.

Sample Input :

4
4
0 0 1 0
1 0 1 0
0 1 0 0
1 1 1 1
4
1 0 0 1
0 0 0 0
0 1 1 0
1 0 0 1
5
1 0 0 1 1
0 0 1 0 0
0 0 0 0 0
1 1 1 1 1
0 0 0 0 0
8
0 0 1 0 0 1 0 0
1 0 0 0 0 0 0 1
0 0 1 0 0 1 0 1
0 1 0 0 0 1 0 0
1 0 0 0 0 0 0 0
0 0 1 1 0 1 1 0
1 0 1 1 0 1 1 0
0 0 0 0 0 0 0 0

Sample output :

1
3
3
9

Constraint :

0 < T < 6 
0 < N < 1009 


=================WORKING CODE=================

#include<stdio.h>

int count_connected_set(int A[1015][1015],int i,int j,int n)
{
    A[i][j]=2;
    if(A[i-1][j-1]==1 && i>0 && j>0 && i<=n && j<=n )     //NW
        count_connected_set(A,i-1,j-1,n);
    if(A[i-1][j]==1 && i>0 && j>0 && i<=n && j<=n)       //N
        count_connected_set(A,i-1,j,n);
    if(A[i-1][j+1]==1 && i>0 && j>0 && i<=n && j<=n)//   //NE
        count_connected_set(A,i-1,j+1,n);
    if(A[i][j-1]==1 && i>0 && j>0 && i<=n && j<=n)       //W
        count_connected_set(A,i,j-1,n);
    if(A[i][j+1]==1 && i>0 && j>0 && i<=n && j<=n)       //E
        count_connected_set(A,i,j+1,n);
    if(A[i+1][j-1]==1 && i>0 && j>0 && i<=n && j<=n)     //SW
        count_connected_set(A,i+1,j-1,n);
    if(A[i+1][j]==1 && i>0 && j>0 && i<=n && j<=n)       //S
        count_connected_set(A,i+1,j,n);
    if(A[i+1][j+1]==1 && i>0 && j>0 && i<=n && j<=n)     //SE
        count_connected_set(A,i+1,j+1,n);
return 1;
}// end of count_connected_set()

int main()
{
    int i,j,t,k,n,A[1015][1015],count;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
                scanf("%d",&A[i][j]); // geting input a test case;
        count =0;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
                if(A[i][j]==1)
                    if(count_connected_set(A,i,j,n))
                        count++;
        }// of for
        printf("%d\n",count);
    }// end of while
return 0;
}


Let me know your thoughts.


8 comments:

  1. This is a nice implementation using recursion, I have not tested it though. However, after finding the number of connected sets, it is difficult to find the actual disjoint connected sets. Check out here to see how this is done:

    http://www.codeding.com/articles/connected-sets-labeling

    ReplyDelete
  2. This code not giving right Answer :-(
    For input:
    1
    4
    1 0 0 1
    0 0 0 0
    0 1 1 0
    1 0 0 1

    The output should be 3

    but this code gives 6

    ReplyDelete
    Replies
    1. hey Sathish,
      I have checked with your input and it gives an expected result

      look the result http://ideone.com/yY11LZ

      Delete
    2. This comment has been removed by the author.

      Delete
    3. yes :- ) . Code in "http://ideone.com/yY11LZ" is working fine..
      But code in this blog is not working as expected.

      Delete
    4. I have copied the code from blog itself.

      Delete
  3. You dont need to check all the directions. Just E,ES,S,SW are enough as the other directions are already covered in previous row or column if there is a "1" present in other directions in future iterations.
    Check this code:
    import java.util.Scanner;

    public class Solution {

    public static void visit(int[][] ar, boolean[][] v,int i, int j){
    int size = ar.length;
    if(ar[i][j] == 1){
    v[i][j] = true;
    if(j>0 && i<size-1){
    visit(ar,v,i+1,j-1);
    }
    if(i<size-1){
    visit(ar,v,i+1,j);
    if(j < size-1)
    visit(ar,v,i+1,j+1);
    }
    if(j<size-1)
    visit(ar,v,i,j+1);
    }
    }

    public static void main(String[] args) {
    int[][] ar;
    int count = 0;
    Scanner sc = new Scanner(System.in);
    int n = sc.nextInt();
    ar = new int[n][n];
    boolean[][] v = new boolean[n][n];
    for(int i=0; i<n ; i++) {
    for(int j=0; j<n; j++){
    ar[i][j] = sc.nextInt();
    v[i][j] = false;
    }
    }

    for(int i=0; i<n ; i++) {
    for(int j=0; j<n; j++){
    if(ar[i][j] == 1 && !v[i][j]){
    count++;
    visit(ar,v,i,j);
    }
    }
    }
    System.out.println(count);
    }
    }

    ReplyDelete
  4. can u pls explain with the stack frame?

    ReplyDelete