题目如下:
7-22 List Components (25 分)
For a given undirected graph with N vertices and E edges, please list all the connected components by both DFS (Depth First Search) and BFS (Breadth First Search). Assume that all the vertices are numbered from 0 to N-1. While searching, assume that we always start from the vertex with the smallest index, and visit its adjacent vertices in ascending order of their indices.
Input Specification:
Each input file contains one test case. For each case, the first line gives two integers N (0<N≤10) and E, which are the number of vertices and the number of edges, respectively. Then E lines follow, each described an edge by giving the two ends. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print in each line a connected component in the format { v1 v2 ... vk }. First print the result obtained by DFS, then by BFS.
Sample Input:
8 6
0 7
0 1
2 0
4 1
2 4
3 5
Sample Output:
{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }
题目规定的输入的顶点数不超过10,因此可以用图的邻接矩阵存储信息;边有可能平行,因此用a[i][j]!=0来判断是否存在边,而非用a[i][j]==1进行判断;主函数代码如下:
int main()
{
//freopen("in.txt","r",stdin);
cin>>N>>E;
for(int i=0;i<E;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[x][y]=a[y][x]+=1;
}
FS(DFS);
FS(BFS);
return 0;
}
#endif
在FS函数中,其参数格式为void (*FS)(int),缺一不可,在循环中,每一次一趟,分两部分,先遍历后输出。图可能不是连通图,因此需要用大括号(按照输出格式要求)将每一趟遍历结果括起来,最好用队列来存放,这样思路比较清晰,格式的控制也比较灵活(体现在if(!q,empty())上);注意要及时清空v[]要及时清空(清为0),因为v是用来记录是否遍历过。代码如下:
void FS(void (*FS)(int))
{
memset(v,0,sizeof(v));
for(int i=0;i<N;i++)
{
if(v[i]==0)//遍历的前提是未遍历过
{
FS(i);
cout<<"{ ";
while(!q.empty())
{
printf("%d ",q.front());
q.pop();
}
cout<<"}\n";
}
}
}
在DFS函数中,用递归实现较为清晰,每碰到一个未遍历的顶点,先不做标记(这一点很重要),也不入队,直接进入下一层,这是为了避免中断继续深入遍历,并且只在下一层标记和入队。代码如下:
void DFS(int x)
{
v[x]=1;
q.push(x);
for(int i=0;i<N;i++)
{
if(v[i]==0&&a[x][i])//邻接顶点
{
DFS(i);
}
}
}
在BFS函数中,用队列实现较为直观,知道队列为空才跳出循环,每趟均需要出队,有时会进队,因此不会陷入死循环的。代码如下:
void BFS(int x)
{
v[x]=1;
q.push(x);
queue<int> qq;
qq.push(x);
while(!qq.empty())
{
int y=qq.front();
qq.pop();
for(int i=0;i<N;i++)
{
if(v[i]==0&&a[y][i])//邻接顶点
{
v[i]=1;
qq.push(i);
q.push(i);
}
}
}
}
总代码如下:
#if 1
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <deque>
#include <map>
#include <set>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
using namespace std;
int a[15][15],N,v[15],E;
queue<int> q;
void DFS(int x)
{
v[x]=1;
q.push(x);
for(int i=0;i<N;i++)
{
if(v[i]==0&&a[x][i])
{
DFS(i);
}
}
}
void BFS(int x)
{
queue<int> qq;
v[x]=1;
q.push(x);
qq.push(x);
while(!qq.empty())
{
int y=qq.front();
qq.pop();
for(int i=0;i<N;i++)
{
if(v[i]==0&&a[y][i])
{
v[i]=1;
qq.push(i);
q.push(i);
}
}
}
}
void FS(void (*FS)(int))
{
memset(v,0,sizeof(v));
for(int i=0;i<N;i++)
{
if(v[i]==0)
{
FS(i);
cout<<"{ ";
while(!q.empty())
{
printf("%d ",q.front());
q.pop();
}
cout<<"}\n";
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
cin>>N>>E;
for(int i=0;i<E;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[x][y]=a[y][x]=1;
}
FS(DFS);
FS(BFS);
return 0;
}
#endif