如下面一個題目爲例,[題目連接]: https://www.luogu.com.cn/problem/P4961
題目中涉及求出八聯通圖的個數,這裏給出這步的代碼:ios
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數組變一變便可。
注意:四連通圖也是八聯通圖,也就是說一個格的也行。數組
下面給出關於那道題目的代碼:spa
#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("%d\n", cnt); }