用dfs遍历联通块(优化)

一、题目(CF 598D)

输入一个n x m的字符矩阵,求从某个空点出发,能碰到多少面墙壁,总共询问k次。(3 ≤m,n ≤1000,1 ≤ k ≤ min(nm,100 000)) 

二、解题思路

用DFS找连通分量:从每个“.”格子出发,递归遍历与之相邻的“*”格子,且写上相同的联通分量(即代码中的blocks数组),同时统计该联通分量边界墙壁面数。由于存在多次查询,我们用blocks[i][j]记录格子(i,j)所在的联通分量标号,用res[i]表示联通分量i的边界墙壁面数。

三、代码实现

 1 #include<stdio.h>
 2 #include<iostream>
 3 #include<string.h>
 4 #include<stdbool.h>
 5 using namespace std;
 6 
 7 const int maxn = 1000 + 10;
 8 const int maxm = 1000 + 10;
 9 const int maxk = 100000 + 10;
10 const int maxx = 1000000 + 10;
11 int n, m;
12 char maze[maxn][maxm];
13 bool vis[maxn][maxm];
14 int blocks[maxn][maxm];
15 int res[maxx];
16 int dx[] = { -1,0,1,0 }, dy[] = { 0,1,0,-1 };
17 int flag = 0;
18 
19 void dfs(int x, int y, int flag,int& sum)   //sum传引用
20 {
21     vis[x][y] = true;
22     blocks[x][y] = flag;
23     for (int i = 0; i < 4; i++)
24     {
25         int xx = x + dx[i]; int yy = y + dy[i];
26         if (xx >= 0 && xx < n && yy >= 0 && yy < m && (!vis[xx][yy]))
27         {
28             if (maze[xx][yy] == '*')
29                 sum++;
30             else
31                 dfs(xx, yy, flag,sum);
32         }
33     }
34 }
35 int main()
36 {
37     int k;
38     scanf("%d%d%d", &n, &m, &k);
39     memset(vis, 0, sizeof(vis));
40 
41     for (int i = 0; i < n; i++)
42         for (int j = 0; j < m; j++)
43             cin >> maze[i][j];
44 
45     for (int i = 0; i < n; i++)
46         for (int j = 0; j < m; j++)
47         {
48             if (maze[i][j] == '.' && (!vis[i][j]))
49             
50             {
51                 int sum = 0;
52                 dfs(i, j, ++flag,sum);
53                 res[flag] = sum;
54             }
55         }
56 
57     while (k--)
58     {
59         int sx, sy;
60         scanf("%d%d", &sx, &sy);
61         printf("%d
", res[blocks[sx - 1][sy - 1]]);
62     }
63     return 0;
64 }
原文地址:https://www.cnblogs.com/lfri/p/9655368.html