题意描述:
要求输出图中连通分支的个数。
最简单的图遍历问题,题目虽然简单,却考察了最基本的遍历知识。
图的常见遍历方式有两种:深度优先遍历和广度优先遍历,他们的作用是将图中的每个点都访问一遍,只不过是顺序不同。
如果把图中的每条边长都相等(比如都是1)的话,深度优先遍历的过程是:
1.任意选定一个点p0作为遍历的起点
2.从未访问节点中任选一个距离p0最近的点进行访问,并标记该点被访问过
3.重复第2步,直到该连通分支中的所有节点都被访问过
说的形象一点,深度优先遍历就是按照层次的顺序访问节点,每一层中的节点与p0有相同的距离。先访问第一层,再访问第二层,……
深度优先遍历过程就是尽可能深的去访问节点,具体过程为:
1.任意选定一个点p0作为遍历的起点
2.当访问到某一个节点p1时,如果p1下面有未被遍历的子节点,我们就接着访问p1的某一个未被遍历子节点,并标记该子节点被访问过,
3.如果p1不存在未被访问的子节点,我们就退回到p1的父节点,并执行第2步
4.执行第2、3步,直到所有节点被访问过。
(递归过程真心不好描述啊~~~)
大家也看出来了,深度优先遍历的是一个递归的过程,因此很容易想到要用到栈这种数据结构,具体实现的时候可以用递归,也可以用栈。看个人习惯了。
广度优先遍历实现就要用到队列了。
以下是poj2386不同实现方式的代码
深度优先遍历,递归实现:
#include<stdio.h>
#include<stdlib.h>
#include<string.h> //stack, Recursion
#define LEN 110
char mp[LEN][LEN];
int N, M;
int d[8][2] = {-1, -1, -1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 0, 1, 1};
//d[][]是各个方向上的增量
void DFS(int x0, int y0)
{
int i, j;
mp[x0][y0] = 'X';//标记该节点被访问过
for(i = 0; i < 8; i++)
{
int x1 = x0 + d[i][0];
int y1 = y0 + d[i][1];
if(mp[x1][y1] == 'W')
DFS(x1, y1);
}
}
int main()
{
int i, j;
while(scanf("%d%d", &N, &M) != EOF)
{
for(i = 1; i <= N; i++)
scanf("%s", &mp[i][1]);
for(i = 0; i <= N + 1; i++)
mp[i][0] = mp[i][M + 1] = '.';
for(i = 0; i <= M + 1; i++)
mp[0][i] = mp[N + 1][i] = '.';
int count = 0;
for(i = 1; i <= N; i++)
for(j = 1; j <= M; j++)
if(mp[i][j] == 'W')
{
count++;
DFS(i, j);
}
printf("%d\n", count);
}
//system("pause");
}深度优先遍历,栈实现:
#include<stdio.h>
#include<stdlib.h>// stack;
#include<string.h>
#define LEN 110
#define LEN1 10010
typedef struct
{
int x;
int y;
}Point;
Point stk[LEN1];
int tp;
char mp[LEN][LEN];
int N, M;
int d[8][2] = {-1, -1, -1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 0, 1, 1};
void DFS(int x0, int y0)
{
int i, j;
stk[0].x = x0;
stk[0].y = y0;
mp[x0][y0] = 'X';
tp = 1;
while(tp != 0)
{
for(i = 0; i < 8; i++)
{
int x1 = stk[tp - 1].x + d[i][0];
int y1 = stk[tp - 1].y + d[i][1];
if(mp[x1][y1] == 'W')
{
mp[x1][y1] = 'X';
stk[tp].x = x1;
stk[tp++].y = y1;
break;
}
}
if(i >= 8)
tp--;
}
}
int main()
{
int i, j;
while(scanf("%d%d", &N, &M) != EOF)
{
for(i = 1; i <= N; i++)
scanf("%s", &mp[i][1]);
for(i = 0; i <= N + 1; i++)
mp[i][0] = mp[i][M + 1] = '.';
for(i = 0; i <= M + 1; i++)
mp[0][i] = mp[N + 1][i] = '.';
int count = 0;
for(i = 1; i <= N; i++)
for(j = 1; j <= M; j++)
if(mp[i][j] == 'W')
{
count++;
DFS(i, j);
}
printf("%d\n", count);
}
//system("pause");
}广度优先遍历:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>// queue
#define LEN 110
#define LEN1 10010
typedef struct
{
int x;
int y;
}Point;
Point q[LEN1];
int f, r;
char mp[LEN][LEN];
int N, M;
int d[8][2] = {-1, -1, -1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 0, 1, 1};
void BFS(int x0, int y0)
{
int i, j;
q[0].x = x0;
q[0].y = y0;
mp[x0][y0] = 'X';
f = 0;
r = 1;
while(f != r)
{
int x = q[f].x;
int y = q[f].y;
f++;
for(i = 0; i < 8; i++)
{
int x1 = x + d[i][0];
int y1 = y + d[i][1];
if(mp[x1][y1] == 'W')
{
mp[x1][y1] = 'X';
q[r].x = x1;
q[r++].y = y1;
}
}
}
}
int main()
{
int i, j;
while(scanf("%d%d", &N, &M) != EOF)
{
for(i = 1; i <= N; i++)
scanf("%s", &mp[i][1]);
for(i = 0; i <= N + 1; i++)
mp[i][0] = mp[i][M + 1] = '.';
for(i = 0; i <= M + 1; i++)
mp[0][i] = mp[N + 1][i] = '.';
int count = 0;
for(i = 1; i <= N; i++)
for(j = 1; j <= M; j++)
if(mp[i][j] == 'W')
{
count++;
BFS(i, j);
}
printf("%d\n", count);
}
//system("pause");
posted on 2012-08-20 12:23
小鼠标 阅读(1592)
评论(0) 编辑 收藏 引用 所属分类:
图论