📜  使用 BFS 的图表中的岛屿

📅  最后修改于: 2021-10-25 05:11:03             🧑  作者: Mango

给定一个布尔二维矩阵,找出岛屿的数量。一组相连的 1 形成一个岛。例如,下面的矩阵包含 5 个岛

例子:

Input : mat[][] = {{1, 1, 0, 0, 0},
                   {0, 1, 0, 0, 1},
                   {1, 0, 0, 1, 1},
                   {0, 0, 0, 0, 0},
                   {1, 0, 1, 0, 1} 
Output : 5

什么是岛?
一组相连的 1 形成一个岛。例如,下面的矩阵包含 5 个岛

{1,  1, 0, 0, 0},
                        {0, 1, 0, 0, 1},
                        {1, 0, 0, 1, 1},
                        {0, 0, 0, 0, 0},
                        {1, 0, 1, 0, 1}

这是标准问题的变体:连通分量。无向图的连通分量是一个子图,其中每两个顶点通过一条路径相互连接,并且不与子图外的其他顶点相连。

例如,下图显示了三个相连的组件。

所有顶点都相互连接的图只有一个连通分量,由整个图组成。这种只有一个连通分量的图称为强连通图。
我们已经讨论了针对岛屿的 DFS 解决方案。这个问题也可以通过在每个组件上应用 BFS() 来解决。在每次 BFS() 调用中,都会访问一个组件或子图。我们将在下一个未访问的组件上调用 BFS。对 BFS() 的调用次数给出了连接组件的数量。也可以使用 BFS。

二维矩阵中的一个单元格可以连接到 8 个邻居。因此,与我们处理所有相邻顶点的标准 BFS() 不同,我们只处理 8 个相邻顶点。我们会跟踪访问过的 1,以免再次访问它们。

C++
// A BFS based solution to count number of
// islands in a graph.
#include 
using namespace std;
 
// R x C matrix
#define R 5
#define C 5
 
// A function to check if a given cell
// (u, v) can be included in DFS
bool isSafe(int mat[R][C], int i, int j,
            bool vis[R][C])
{
    return (i >= 0) && (i < R) &&
           (j >= 0) && (j < C) &&
           (mat[i][j] && !vis[i][j]);
}
 
void BFS(int mat[R][C], bool vis[R][C],
         int si, int sj)
{
 
    // These arrays are used to get row and
    // column numbers of 8 neighbours of
    // a given cell
    int row[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
    int col[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
 
    // Simple BFS first step, we enqueue
    // source and mark it as visited
    queue > q;
    q.push(make_pair(si, sj));
    vis[si][sj] = true;
 
    // Next step of BFS. We take out
    // items one by one from queue and
    // enqueue their univisited adjacent
    while (!q.empty()) {
 
        int i = q.front().first;
        int j = q.front().second;
        q.pop();
 
        // Go through all 8 adjacent
        for (int k = 0; k < 8; k++) {
            if (isSafe(mat, i + row[k],
                       j + col[k], vis)) {
             vis[i + row[k]][j + col[k]] = true;
             q.push(make_pair(i + row[k], j + col[k]));
            }
        }
    }
}
 
// This function returns number islands (connected
// components) in a graph. It simply works as
// BFS for disconnected graph and returns count
// of BFS calls.
int countIslands(int mat[R][C])
{
    // Mark all cells as not visited
    bool vis[R][C];
    memset(vis, 0, sizeof(vis));
 
    // Call BFS for every unvisited vertex
    // Whenever we see an univisted vertex,
    // we increment res (number of islands)
    // also.
    int res = 0;
    for (int i = 0; i < R; i++) {
        for (int j = 0; j < C; j++) {
            if (mat[i][j] && !vis[i][j]) {
                BFS(mat, vis, i, j);
                res++;
            }
        }
    }
 
    return res;
}
 
// main function
int main()
{
    int mat[][C] = { { 1, 1, 0, 0, 0 },
                     { 0, 1, 0, 0, 1 },
                     { 1, 0, 0, 1, 1 },
                     { 0, 0, 0, 0, 0 },
                     { 1, 0, 1, 0, 1 } };
 
    cout << countIslands(mat);
 
    return 0;
}


Java
// A BFS based solution to count number of
// islands in a graph.
import java.util.*;
 
class GFG
{
 
// R x C matrix
static final int R = 5;
static final int C = 5 ;
static class pair
{
    int first, second;
    public pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
}
 
// A function to check if a given cell
// (u, v) can be included in DFS
static boolean isSafe(int mat[][], int i, int j,
                       boolean vis[][])
{
    return (i >= 0) && (i < R) &&
        (j >= 0) && (j < C) &&
        (mat[i][j]==1 && !vis[i][j]);
}
 
static void BFS(int mat[][], boolean vis[][],
                int si, int sj)
{
 
    // These arrays are used to get row and
    // column numbers of 8 neighbours of
    // a given cell
    int row[] = { -1, -1, -1, 0, 0, 1, 1, 1 };
    int col[] = { -1, 0, 1, -1, 1, -1, 0, 1 };
 
    // Simple BFS first step, we enqueue
    // source and mark it as visited
    Queue q = new LinkedList();
    q.add(new pair(si, sj));
    vis[si][sj] = true;
 
    // Next step of BFS. We take out
    // items one by one from queue and
    // enqueue their univisited adjacent
    while (!q.isEmpty())
    {
 
        int i = q.peek().first;
        int j = q.peek().second;
        q.remove();
 
        // Go through all 8 adjacent
        for (int k = 0; k < 8; k++)
        {
            if (isSafe(mat, i + row[k],
                    j + col[k], vis))
            {
                vis[i + row[k]][j + col[k]] = true;
                q.add(new pair(i + row[k], j + col[k]));
            }
        }
    }
}
 
// This function returns number islands (connected
// components) in a graph. It simply works as
// BFS for disconnected graph and returns count
// of BFS calls.
static int countIslands(int mat[][])
{
    // Mark all cells as not visited
    boolean [][]vis = new boolean[R][C];
 
    // Call BFS for every unvisited vertex
    // Whenever we see an univisted vertex,
    // we increment res (number of islands)
    // also.
    int res = 0;
    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            if (mat[i][j]==1 && !vis[i][j])
            {
                BFS(mat, vis, i, j);
                res++;
            }
        }
    }
    return res;
}
 
// Driver code
public static void main(String[] args)
{
    int mat[][] = { { 1, 1, 0, 0, 0 },
                    { 0, 1, 0, 0, 1 },
                    { 1, 0, 0, 1, 1 },
                    { 0, 0, 0, 0, 0 },
                    { 1, 0, 1, 0, 1 } };
 
    System.out.print(countIslands(mat));
}
}
 
// This code is contributed by PrinciRaj1992


Python3
# A BFS based solution to count number of
# islands in a graph.
from collections import deque
 
# A function to check if a given cell
# (u, v) can be included in DFS
def isSafe(mat, i, j, vis):
     
    return ((i >= 0) and (i < 5) and 
            (j >= 0) and (j < 5) and
          (mat[i][j] and (not vis[i][j])))
 
def BFS(mat, vis, si, sj):
     
    # These arrays are used to get row and
    # column numbers of 8 neighbours of
    # a given cell
    row = [-1, -1, -1, 0, 0, 1, 1, 1]
    col = [-1, 0, 1, -1, 1, -1, 0, 1]
 
    # Simple BFS first step, we enqueue
    # source and mark it as visited
    q = deque()
    q.append([si, sj])
    vis[si][sj] = True
 
    # Next step of BFS. We take out
    # items one by one from queue and
    # enqueue their univisited adjacent
    while (len(q) > 0):
        temp = q.popleft()
 
        i = temp[0]
        j = temp[1]
 
        # Go through all 8 adjacent
        for k in range(8):
            if (isSafe(mat, i + row[k], j + col[k], vis)):
                vis[i + row[k]][j + col[k]] = True
                q.append([i + row[k], j + col[k]])
 
# This function returns number islands (connected
# components) in a graph. It simply works as
# BFS for disconnected graph and returns count
# of BFS calls.
def countIslands(mat):
      
    # Mark all cells as not visited
    vis = [[False for i in range(5)]
                  for i in range(5)]
    # memset(vis, 0, sizeof(vis));
 
    # 5all BFS for every unvisited vertex
    # Whenever we see an univisted vertex,
    # we increment res (number of islands)
    # also.
    res = 0
 
    for i in range(5):
        for j in range(5):
            if (mat[i][j] and not vis[i][j]):
                BFS(mat, vis, i, j)
                res += 1
 
    return res
 
# Driver code
if __name__ == '__main__':
     
    mat = [ [ 1, 1, 0, 0, 0 ],
            [ 0, 1, 0, 0, 1 ],
            [ 1, 0, 0, 1, 1 ],
            [ 0, 0, 0, 0, 0 ],
            [ 1, 0, 1, 0, 1 ]]
 
    print (countIslands(mat))
 
# This code is contributed by mohit kumar 29


C#
// A BFS based solution to count number of
// islands in a graph.
using System;
using System.Collections.Generic;
 
class GFG
{
 
// R x C matrix
static readonly int R = 5;
static readonly int C = 5 ;
class pair
{
    public int first, second;
    public pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
}
 
// A function to check if a given cell
// (u, v) can be included in DFS
static bool isSafe(int [,]mat, int i, int j,
                    bool [,]vis)
{
    return (i >= 0) && (i < R) &&
        (j >= 0) && (j < C) &&
        (mat[i, j]==1 && !vis[i, j]);
}
 
static void BFS(int [,]mat, bool [,]vis,
                int si, int sj)
{
 
    // These arrays are used to get row and
    // column numbers of 8 neighbours of
    // a given cell
    int []row = { -1, -1, -1, 0, 0, 1, 1, 1 };
    int []col = { -1, 0, 1, -1, 1, -1, 0, 1 };
 
    // Simple BFS first step, we enqueue
    // source and mark it as visited
    List q = new List();
    q.Add(new pair(si, sj));
    vis[si, sj] = true;
 
    // Next step of BFS. We take out
    // items one by one from queue and
    // enqueue their univisited adjacent
    while (q.Count != 0)
    {
        int i = q[0].first;
        int j = q[0].second;
        q.RemoveAt(0);
 
        // Go through all 8 adjacent
        for (int k = 0; k < 8; k++)
        {
            if (isSafe(mat, i + row[k],
                    j + col[k], vis))
            {
                vis[i + row[k], j + col[k]] = true;
                q.Add(new pair(i + row[k], j + col[k]));
            }
        }
    }
}
 
// This function returns number islands (connected
// components) in a graph. It simply works as
// BFS for disconnected graph and returns count
// of BFS calls.
static int countIslands(int [,]mat)
{
    // Mark all cells as not visited
    bool [,]vis = new bool[R, C];
 
    // Call BFS for every unvisited vertex
    // Whenever we see an univisted vertex,
    // we increment res (number of islands)
    // also.
    int res = 0;
    for (int i = 0; i < R; i++)
    {
        for (int j = 0; j < C; j++)
        {
            if (mat[i, j]==1 && !vis[i, j])
            {
                BFS(mat, vis, i, j);
                res++;
            }
        }
    }
    return res;
}
 
// Driver code
public static void Main(String[] args)
{
    int [,]mat = { { 1, 1, 0, 0, 0 },
                    { 0, 1, 0, 0, 1 },
                    { 1, 0, 0, 1, 1 },
                    { 0, 0, 0, 0, 0 },
                    { 1, 0, 1, 0, 1 } };
 
    Console.Write(countIslands(mat));
}
}
 
// This code is contributed by 29AjayKumar


Javascript


输出:
5

时间复杂度:O(ROW * COL),其中 ROW 是行数,COL 是矩阵中的 COLUMNS 数。

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程