1. 程式人生 > 實用技巧 >bfs與dfs基礎

bfs與dfs基礎

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;
}

待續…