­

利用DFS算出有多少个连通图

  • 2020 年 2 月 11 日
  • 筆記

以下面一个题目为例,[题目链接]: https://www.luogu.com.cn/problem/P4961 题目中涉及求出八联通图的个数,这里给出这步的代码:

    memset(vis, 0, sizeof(vis));      int cnt = 0;      for(int i = 0; i < n; i++)      {          for(int j = 0; j < m; j++)          {              if(!bomb[i][j] && !vis[i][j])              {                  ++cnt;                  vis[i][j] = 1;                  dfs(i, j);              }          }      }
void dfs(int x, int y)  {      for(int i = 0; i < 8; i++)      {          int xx = x + dx[i];          int yy = y + dy[i];          if(xx >= 0 && xx < n && yy >= 0 && yy < m && !vis[xx][yy] && !bomb[xx][yy])          {              vis[xx][yy] = 1;              dfs(xx, yy);          }      }  }

上面介绍的是求八连通图的个数,类似,求四联通图的个数也是相似的做法,只需把dx,dy数组变一变即可。 注意:四连通图也是八联通图,也就是说一个格的也行。

下面给出关于那道题目的代码:

#include<iostream>  #include<cstdio>  #include<cstring>  using namespace std;  const int maxn = 2000;  int n, m;  int dx[] = {0, 0, -1, -1, -1, 1, 1, 1};  int dy[] = {1, -1, 0, 1, -1, 0, 1, -1};  int bomb[maxn][maxn], vis[maxn][maxn];  void dfs(int x, int y)  {      for(int i = 0; i < 8; i++)      {          int xx = x + dx[i];          int yy = y + dy[i];          if(xx >= 0 && xx < n && yy >= 0 && yy < m && !vis[xx][yy] && !bomb[xx][yy])          {              vis[xx][yy] = 1;              dfs(xx, yy);          }      }  }  int main()  {      freopen("input.txt", "r", stdin);      freopen("output.txt", "w", stdout);      scanf("%d %d", &n, &m);      for(int i = 0; i < n; i++)      {          for(int j = 0; j < m; j++)          {              scanf("%d", &bomb[i][j]);              if(bomb[i][j])                  bomb[i][j] = -1;          }      }      for(int i = 0; i < n; i++)      {          for(int j = 0; j < m; j ++)          {              if(bomb[i][j] == -1)                  continue;              for(int ans = 0; ans < 8; ans++)              {                  int xx = dx[ans] + i;                  int yy = dy[ans] + j;                  if(xx >= 0 && xx < n && yy >= 0 && yy < m && bomb[xx][yy] == -1)                      ++bomb[i][j];              }          }      }      memset(vis, 0, sizeof(vis));      int cnt = 0;      for(int i = 0; i < n; i++)      {          for(int j = 0; j < m; j++)          {              if(!bomb[i][j] && !vis[i][j])              {                  ++cnt;                  vis[i][j] = 1;                  dfs(i, j);              }          }      }      for(int i = 0; i < n; i++)      {          for(int j = 0; j < m; j++)          {              if(bomb[i][j] != 0 && bomb[i][j] != -1)              {                  int flag = 0;                  for(int k = 0; k < 8; k++)                  {                      int xx = i + dx[k];                      int yy = j + dy[k];                      if(xx < 0 || xx >= n || yy < 0 || yy >= m)                          continue;                      if(xx >= 0 && xx < n && yy >= 0 && yy < m && bomb[xx][yy] == 0)                      {                          flag = 1;                          break;                      }                  }                  if(!flag)                      ++cnt;              }          }      }        printf("%dn", cnt);  }