dfs讲解

输入两种符号@*, 求@上下左右连在一起的块数。

 

看作栈,每找到一个就处理那一个,找不到的时候返回上一层。直到第一层都结束了。

 

1、直接看程序和样例吧 和 输出的截图吧。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <algorithm>
 8 #define LL long long
 9 const int maxn = 100+10;
10 using namespace std;
11 int n, m, vis[maxn][maxn];
12 char s[maxn][maxn];
13 int check(int x, int y)
14 {
15     if(x>=0&&x<n&&y>=0&&y<m) return 1;
16     return 0;
17 }
18 void dfs(int x, int y)
19 {
20     if(s[x][y]=='*'||vis[x][y]||!check(x, y))
21     return;
22     vis[x][y] = 1;
23     printf("%d %d\n", x, y);
24     dfs(x, y+1); dfs(x+1, y);
25     dfs(x, y-1); dfs(x-1, y);
26 }
27 int main()
28 {
29     int i, j;
30     while(cin>>n>>m)
31     {
32         if(n==0 && m==0) break;
33 
34         memset(vis, 0, sizeof(vis));
35         ans = 0;
36         for(i = 0; i < n; i++)
37         for(j = 0; j < m; j++)
38         cin>>s[i][j];
39 
40         dfs(1, 1);
41     }
42     return 0;
43 }
44 /*
45 5 4
46 *@**
47 *@@*
48 *@**
49 @@@*
50 @@**
51 */

 

 

2、改了输出位置之后:

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <algorithm>
 8 #define LL long long
 9 const int maxn = 100+10;
10 using namespace std;
11 int n, m, vis[maxn][maxn];
12 char s[maxn][maxn];
13 int check(int x, int y)
14 {
15     if(x>=0&&x<n&&y>=0&&y<m) return 1;
16     return 0;
17 }
18 void dfs(int x, int y)
19 {
20     printf("%d %d\n", x, y);  //改了位置
21     if(s[x][y]=='*'||vis[x][y]||!check(x, y))
22     return;
23     vis[x][y] = 1;
24     dfs(x, y+1); dfs(x+1, y);
25     dfs(x, y-1); dfs(x-1, y);
26 }
27 int main()
28 {
29     int i, j;
30     while(cin>>n>>m)
31     {
32         if(n==0 && m==0) break;
33 
34         memset(vis, 0, sizeof(vis));
35         for(i = 0; i < n; i++)
36         for(j = 0; j < m; j++)
37         cin>>s[i][j];
38 
39         dfs(1, 1);
40     }
41     return 0;
42 }
43 /*
44 5 4
45 *@**
46 *@@*
47 *@**
48 @@@*
49 @@**
50 */

 

3、需要vis[]还原的。

如从求从s到t 的最短路,因为一个点可能被多条路使用,所以一条路用完了以后要把vis【】恢复成0。

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <cstdio>
 6 #include <vector>
 7 #include <algorithm>
 8 #define LL long long
 9 const int maxn = 100+10;
10 const int INF = 1<<28;
11 using namespace std;
12 char s[maxn][maxn];
13 int n, m, vis[maxn][maxn], ans;
14 int bo(int a, int b)
15 {
16     if(a>=0&&a<n&&b>=0&&b<m) return 1;
17     return 0;
18 }
19 
20 void dfs(int a, int b, int tmp)
21 {
22     if(s[a][b]=='t')
23     {
24         if(tmp < ans)
25             ans = tmp;
26         cout<<tmp<<endl;
27         return;
28     }
29     if(!bo(a, b)) return;
30     if(s[a][b]=='#') return;
31     if(vis[a][b]) return;
32 
33     printf("%d %d\n", a, b);
34     vis[a][b] = 1;
35     dfs(a, b+1, tmp+1);
36     dfs(a+1, b, tmp+1);
37     dfs(a, b-1, tmp+1);
38     dfs(a-1, b, tmp+1);
39     vis[a][b] = 0;
40 }
41 int main()
42 {
43     int i, j;
44     while(cin>>n>>m)
45     {
46         memset(vis, 0, sizeof(vis));
47         getchar();
48         ans = INF;
49         for(i = 0; i < n; i++)
50             for(j = 0; j < m; j++)
51                 cin>>s[i][j];
52 
53         dfs(1, 1, 0);
54         cout<<ans<<endl;
55     }
56     return 0;
57 }
58 /*
59 5 7
60 ###...#
61 #s..#.#
62 #.###.#
63 #.....#
64 #####.t
65 */

 

4、tc srm 648 div2 500;

用dfs来判断图的联通分量个数。

题目:

Lun the dog has found an undirected graph in Shuseki Forest. The graph consisted of N vertices and some edges. The vertices of the graph were numbered 0 through N-1. Each edge connected a different pair of vertices.

You are given the description of the graph in a vector <string> graph with N elements, each containing N characters. For each i and j, graph[i][j] will be 'Y' if vertex i and vertex j are connected by an edge, and 'N' otherwise. (Note that for each i, graph[i][i] will be 'N': there are no self-loops.)

Lun is interested in articulation pairs in this graph. An articulation pair is an unordered pair of two different vertices whose deletion increases the number of connected components in the graph. (The deletion of a vertex also removes all edges incident with that vertex.)

Return the number of the articulation pairs in Lun's graph.

 

Notes
-
You are not given the value of N explicitly, but you can determine it as the number of elements in graph.
-
Two vertices belong to the same connected component if and only if we can reach one of them from the other by following a sequence of zero or more edges.
Constraints
-
graph will contain between 3 and 20 elements, inclusive.
-
Each element of graph will contain N characters, where N is the number of the elements in graph.
-
Each character of each element of graph will be either 'Y' or 'N'.
-
For each valid i and j, graph[i][j] will be equal to graph[j][i].
-
For each valid i, graph[i][i] will be 'N'.

题意:给一个矩阵Y表示两个点相连,N表示不相连。最多有20个点,如果删掉其中的两个点

会使图中的联通分量增加,问有多少个这样的点对。

代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <algorithm>
 7 #include <vector>
 8 #define LL __int64
 9 const int maxn = 20 + 10;
10 using namespace std;
11 vector<string>g;
12 int a, b, n;
13 int vis[maxn];
14 
15 class Fragile2
16 {
17     public:
18       void dfs(int x) //把与x连通的标记出来。
19       {
20          for(int i = 0; i < n; i++)
21          if(vis[i]==0 && g[x][i]=='Y' && i!=a && i!=b)
22          {
23              vis[i] = 1;
24              dfs(i);
25          }
26       }
27       int cal()
28       {
29           int i, ret = 0;
30           memset(vis, 0, sizeof(vis));
31           for(i = 0; i < n; i++)
32           {
33               if(vis[i]==0 && i!=a && i!=b) //a, b用的很巧妙,直接不让a,b, 
34                                             //dfs相当于切断了a, b与图中的所有联系,相当于删除了a, b;
35               {
36                   dfs(i);           //经过上面的判断条件之后,很多就不会dfs了。
37                   ret ++;
38               }
39           }
40           return ret;
41       }
42       int countPairs(vector <string> graph)
43       {
44          int ans = 0, sum;
45          g = graph;
46          n = g.size();
47          a = -1; b = -1;
48          sum = cal();   //计算初始的连通分量的个数
49          for(a = 0; a < n; a++)
50          for(b = a+1; b < n; b++) //暴力两个点
51          {
52              int ret = cal();
53              if(ret > sum)
54              ans ++;
55          }
56          return ans;
57       }
58 };

 

5、dfs判断环, 50*50的矩阵

Each cell contains a dot that has some color. We will use different uppercase Latin characters to express different colors.

The key of this game is to find a cycle that contain dots of same color. Consider 4 blue dots on the picture forming a circle as an example. Formally, we call a sequence of dots d1, d2, ..., dk a cycle if and only if it meets the following condition:

  1. These k dots are different: if i ≠ j then di is different from dj.
  2. k is at least 4.
  3. All dots belong to the same color.
  4. For all 1 ≤ i ≤ k - 1: di and di + 1 are adjacent. Also, dk and d1 should also be adjacent. Cells x and y are called adjacent if they share an edge.

Determine if there exists a cycle on the field.

Input

The first line contains two integers n and m (2 ≤ n, m ≤ 50): the number of rows and columns of the board.

Then n lines follow, each line contains a string consisting of m characters, expressing colors of dots in each line. Each character is an uppercase Latin letter.

Output

Output "Yes" if there exists a cycle, and "No" otherwise.

Sample Input

Input
3 4
AAAA
ABCA
AAAA
Output
Yes

题意:给一个矩阵,求有没有相同的字母连成环,环上至少有四个字母。
分析:
就是枚举每一个点,假设以这个点为环上的点,dfs判断能不能回来, 注意图的还原 和 剪枝
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cstdlib>
 5 #include <cmath>
 6 #include <algorithm>
 7 #define LL __int64
 8 const int maxn = 1e2 + 10;
 9 using namespace std;
10 char g[maxn][maxn];
11 int vis[maxn][maxn], n, m, x, y;
12 int f;
13 
14 void dfs(int a, int b, int num)
15 {
16     if(f) return;  //这个很重要,不然会TLE
17     if(a==x && b==y && num>=4)
18     {
19           f = 1;
20           return;
21     }
22     if(a>=0 && a<n && b>=0 && b<m && g[a][b]==g[x][y])
23       if(vis[a][b]==0)
24       {
25           vis[a][b] = 1; 
26           dfs(a+1, b, num+1);  dfs(a, b+1, num+1);
27           dfs(a-1, b, num+1);  dfs(a, b-1, num+1);
28           vis[a][b] = 0;  //需要还原回来,不能把所有相连的全vis,因为其他部分有可能形成环
29       }
30 }
31 int main()
32 {
33     int i, j;
34     while(~scanf("%d%d", &n, &m))
35     {
36         f = 0;
37         memset(vis, 0, sizeof(vis));
38         for(i = 0; i < n; i++)
39          scanf("%s", g[i]);
40         for(i = 0; i < n; i++)
41         {
42             if(f) break;
43             for(j = 0; j < m; j++)
44             {
45                 x = i, y = j;
46                 dfs(i, j, 0);
47                 if(f) break;
48                 vis[i][j] = 1;
49             }
50         }
51         if(f) cout<<"Yes"<<endl;
52         else  cout<<"No"<<endl;
53     }
54     return 0;
55 }

 

posted @ 2014-07-29 09:52  水门  阅读(383)  评论(0)    收藏  举报