1. 程式人生 > >06-圖1 列出連通集(25 分)

06-圖1 列出連通集(25 分)

給定一個有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; }