題意描述:
要求輸出圖中連通分支的個數(shù)。
最簡單的圖遍歷問題,題目雖然簡單,卻考察了最基本的遍歷知識。
圖的常見遍歷方式有兩種:深度優(yōu)先遍歷和廣度優(yōu)先遍歷,他們的作用是將圖中的每個點都訪問一遍,只不過是順序不同。
如果把圖中的每條邊長都相等(比如都是1)的話,深度優(yōu)先遍歷的過程是:
1.任意選定一個點p0作為遍歷的起點
2.從未訪問節(jié)點中任選一個距離p0最近的點進行訪問,并標記該點被訪問過
3.重復(fù)第2步,直到該連通分支中的所有節(jié)點都被訪問過
說的形象一點,深度優(yōu)先遍歷就是按照層次的順序訪問節(jié)點,每一層中的節(jié)點與p0有相同的距離。先訪問第一層,再訪問第二層,……
深度優(yōu)先遍歷過程就是盡可能深的去訪問節(jié)點,具體過程為:
1.任意選定一個點p0作為遍歷的起點
2.當訪問到某一個節(jié)點p1時,如果p1下面有未被遍歷的子節(jié)點,我們就接著訪問p1的某一個未被遍歷子節(jié)點,并標記該子節(jié)點被訪問過,
3.如果p1不存在未被訪問的子節(jié)點,我們就退回到p1的父節(jié)點,并執(zhí)行第2步
4.執(zhí)行第2、3步,直到所有節(jié)點被訪問過。
(遞歸過程真心不好描述啊~~~)
大家也看出來了,深度優(yōu)先遍歷的是一個遞歸的過程,因此很容易想到要用到棧這種數(shù)據(jù)結(jié)構(gòu),具體實現(xiàn)的時候可以用遞歸,也可以用棧。看個人習(xí)慣了。
廣度優(yōu)先遍歷實現(xiàn)就要用到隊列了。
以下是poj2386不同實現(xiàn)方式的代碼
深度優(yōu)先遍歷,遞歸實現(xiàn):


#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';//標記該節(jié)點被訪問過
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");
}深度優(yōu)先遍歷,棧實現(xiàn):


#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");
}廣度優(yōu)先遍歷:


#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
小鼠標 閱讀(1603)
評論(0) 編輯 收藏 引用 所屬分類:
圖論