bfs與dfs基礎
阿新 • • 發佈:2020-11-19
bfs像二叉樹的層序遍歷
像這個圖走bfs就{1, 2, 3, 4, 5, 6, 7, 8}這樣走;
dfs就{1, 2, 5, 6, 3, 7, 8, 4}。
bfs與queue相結合,走到哪就把哪加進queue,出時把最先進的那個點彈出,同時把彈出這個點有關連的點加入queue。
例:LuoguP5318dfs與bfs運用
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 5; ll n, m, k, q, p; string s, r; vector<int>a[maxn];//存該點可以走向哪些點,vector第二維可以一直存點 int b[maxn];//用來判斷該點有木有經過 void dfs(int x){ if(x >= 1 && x <= n){//經過就輸出和標記 b[x] = 1; cout<<x<<' '; } for(int i = 0; i < a[x].size(); i++){ if(!b[a[x][i]])//把沒經過的點dfs遍歷一遍 dfs(a[x][i]); }return; } void bfs(){ queue<int>q;//佇列存點 q.push(1);//點1先進 while(!q.empty()){//判斷空否 int p = q.front(); if(b[p] == 0){//隊首未經歷就輸出 b[p] = 1;//標記 cout<<p<<' '; } else{//經歷過直接彈出到下一次迴圈 q.pop(); continue; }for(int i = 0; i < a[p].size(); i++){ if(!b[a[p][i]])//把點p可以走向的點加入queue q.push(a[p][i]); } q.pop();//不要了彈出 } } int main(){ //ios_base::sync_with_stdio(0); //cin.tie(); cout.tie(); cin>>n>>m; for(int i = 1; i <= m; i++){ cin>>p>>q; a[p].push_back(q);//點p可以走向q } for(int i = 1; i <= n; i++){ sort(a[i].begin(), a[i].end());//依題意從小到大排序,如果大到小自己寫個cmp函式 } dfs(1);//從1開始 memset(b, 0, sizeof(b));//b陣列歸零用於bfs cout<<endl; bfs(); return 0; }
例:LuoguP3916反向建邊的dfs
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 1e5 + 5; ll n, m, k, q, p; string s, r; vector<int>a[maxn]; int b[maxn], c[maxn];//b標記,c存到達最大值 void dfs(int x){ for(int i = 0; i < a[x].size(); i++){//a[x].size()是可以到x點的數 if(b[a[x][i]] == 0){//看看是否標記 b[a[x][i]] = 1;//現在經歷了要標記 c[a[x][i]] = c[x];//c[x]是x能到達的最大值,而a[x][i]能到x,所以它到最大值也是x能到最大值 dfs(a[x][i]);//繼續深搜可以到a[x][i]的點 } } } int main(){ //ios_base::sync_with_stdio(0); //cin.tie(); cout.tie(); cin>>n>>m; for(int i = 1; i <= m; i++){ cin>>p>>q; a[q].push_back(p);//反向建邊,a[q]裡為能到達q的點 } for(int i = n; i >= 1; i--){//因為求到達最大,從n倒著迴圈就行 if(b[i] == 0){//看看是否經歷 b[i] = 1;//現在要經歷了標記 c[i] = i;//自己到自己最大 dfs(i);//深度搜能到i點的點把他們可以到達最大值設為i } } for(int i = 1; i <= n; i++) cout<<c[i]<<' ';//輸出1到n能到的最大點 return 0; }
待續…