06-圖1 列出連通集(25 分)
阿新 • • 發佈:2019-02-18
給定一個有N個頂點和E條邊的無向圖,請用DFS和BFS分別列出其所有的連通集。假設頂點從0到N−1編號。進行搜尋時,假設我們總是從編號最小的頂點出發,按編號遞增的順序訪問鄰接點。
輸入格式:
輸入第1行給出2個整數N(0
思路:
1.DFS相當於圖版的前序遍歷,和二叉樹的前序遍歷唯一的區別在於,每次遞迴呼叫DFS的時候,二叉樹是遞迴遍歷左右子樹,而圖是要把每一個當前點的鄰接點都遍歷一遍。只有數量上的區別,本質相同。
2.BFS相當於圖版的層次遍歷,區別只在於每次入隊的節點數可能會大於2,與DFS和前序遍歷的關係相似。換句話說,BFS和DFS是泛化的層次遍歷和前序遍歷,BFS和DFS在所給的圖為二叉樹時,可以當作層次遍歷和前序遍歷來用。
通過上面的分析,可以對樹是一種特殊形態的圖有更深的理解。
PS:deque在本題中並不特別合適,用queue更好,deque是雙端佇列,queue基本就是我們資料結構學的先進先出的佇列,相關知識為C++ STL的內容。推薦中國大學mooc北大郭煒老師的課(https://www.icourse163.org/learn/PKU-1002029030?tid=1002785058#/learn/content),第八週第九周系統講解了STL的用法。
#include<iostream>
#include<cstdio>
#include<deque>
#include<cstring>
using namespace std;
const int MAX_N = 10;
int g[MAX_N][MAX_N];
int visited[MAX_N]={0};//用來標記節點是否已經輸出
void BFS(int N){
deque<int> q;//用來做層次遍歷
memset(visited,0,sizeof(visited));
for(int j = 0; j < N; j++){
if(visited[j])
continue;
cout<<"{ ";
q.push_back(j);
while (q.size()!=0){
int head = q.front();
visited[head]=true;
q.pop_front();
for(int i = 0; i < N; i++){
if(g[head][i]==1&&visited[i]==false){
q.push_back(i);
visited[i] = true;
}
}
cout<<head<<" ";
}
cout<<"}"<<endl;
}
return;
}
void DFS(int start, int N){
visited[start]=true;
cout<<start<<" ";
int i;
for(i = 0; i <= N; i++){
if(g[start][i]==1&&visited[i]==false){
DFS(i,N);
}
}
if(i==N)
return;
}
int main(){
int N,E;
cin >> N >> E;
for(int i = 0; i < E; i++){
int x,y;
cin >> x >> y;
g[x][y] = 1;
g[y][x] = 1;
}
//DFS 圖版的前序遍歷
memset(visited,0,sizeof(visited));
while(1){
int j;
for(j=0; j < N; j++){
if(visited[j]==0){
break;
}
}
if(j==N)
break;
cout<<"{ ";
for(j=0; j < N; j++){
if(visited[j]==0){
DFS(j,N);
break;
}
}
cout<<"}"<<endl;
}
//BFS 圖版的層次遍歷
BFS(N);
return 0;
}