# 圖論 ## dfs ![](https://i.imgur.com/10Qd8Q9.png) 深度優先搜尋法 以下為鄰接矩陣的作法 ```cpp= #include <iostream> using namespace std; int vertex,edge; bool visited[10] = {false}; int maps[10][10] = {{0}}; void dfs(int node); void print(); int main(){ cin >> vertex >> edge; int tmp1,tmp2; for(int i = 0;i < edge;i++){ cin >> tmp1 >> tmp2; maps[tmp1-1][tmp2-1] = maps[tmp2-1][tmp1-1] = 1; } print(); cout << endl; for(int i = 0;i < vertex;i++){ if(!visited[i]) dfs(i); } return 0; } void dfs(int node){ cout << node+1 << " "; visited[node] = true; for(int i = 0;i < edge;i++){ if(!visited[i] && maps[node][i] == 1) dfs(i); } } void print(){ for(int i = 0;i < vertex;i++){ for(int j = 0;j < vertex;j++){ cout << maps[i][j] << " "; } cout << endl; } } ``` ```cpp= #include <iostream> #include <algorithm> #define N 50 #define M 50 using namespace std; int graph[N][M]; int visited[N]; void dfs(int n); int main(){ fill(visited,visited+N,0); int n,m; cin >> n >> m; int tmp1,tmp2; for(int i = 0;i < n;i++){ cin >> tmp1 >> tmp2; graph[tmp1][tmp2] = 1; graph[tmp2][tmp1] = 1; } cout << endl; visited[1] = 1; dfs(1); return 0; } void dfs(int n){ cout << n << " "; for(int i = 1;i <= 6;i++){ if(graph[n][i] == 1 && visited[i] == 0){ visited[i] = 1; dfs(i); } } } ``` 以上兩種的寫法都是dfs,只是有一些部分不太一樣。 我們程式講解就拿第二個為例子,由於我們是鄰接矩陣,所以建立一個二維陣列來存放資料比較清楚,再建立一個陣列存放node是否被走訪過,那由於此圖是undirected graph(無向圖),所以假設1連到2,就等於2連到1,接著進入dfs(),我們使用一個迴圈去跑,如果沒被走過且看我們傳入的n有相連的話就將他走訪遞迴,讓走訪過程中走到不能再走後就回傳,雖然我們設的是void,但可以想成回傳一個NULL。 ## bfs ```cpp= #include <iostream> #include <cstring> #define vertex 6 #define edge 7 using namespace std; bool visited[vertex]; int line[edge][2]; void bfs(int n){ int que[100]; visited[n] = true; int last = -1,first = -1; que[++last] = n; while(first < last){ int pop = que[++first]; cout << pop << " "; for(int i = 0;i < vertex;i++){ if(visited[i] == 0 && line[pop][i] == 1){ que[++last] = i; visited[i] = true; } } } } int main(){ fill(visited,visited+vertex,0); memset(line,0,sizeof(line)); for(int i = 0;i < edge;i++){ int tmp1,tmp2; cin >> tmp1 >> tmp2; line[tmp1][tmp2] = line[tmp2][tmp1] = 1; } for(int i = 0;i < vertex;i++){ if(!visited[i]){ bfs(i); } } return 0; } ``` 首先來看廣度優先搜尋法和深度優先搜尋法的差異: dfs是用在深度 > 廣度,而bfs是用在廣度 > 深度,所以在做bfs時要注意,我們不是把路走訪到不能走為止,而是走到一個node就要將node同一階層的人都走過,再繼續往下走。 由於dfs和bfs有一些地方相同,所以相似的地方我就不多做贅述了,在bfs()裡我們建立一個佇列(queue),其實這邊也可以使用STL的queue,但這裡我還是選擇製作一個陣列做撰寫,這邊還有一個地方比較特別的就是我們建立兩個變數分別稱為first和last,代表我們對queue的index,這也是我為甚麼不使用STL的queue,因為對於初學,有index的程式比較好理解,我們先將傳入的n加入佇列裡,接著進入迴圈,這裡的條件是說如果last == first 的時候代表佇列裡已經沒有元素了,所以此時就跳出迴圈,那迴圈的第一個部分是說我們將已經在佇列最前面的元素輸出,也就是pop,剩下的就和dfs類似了。