经典BFS
-
的特点是逐层扩散,步长一致,从源点到目标点扩散的层数就是最短路
-
可以是单源,也可以是多源
-
频繁使用队列,实现形式分为 单点弹出 和 整层弹出
-
节点进入队列时标记状态,防止死循环
-
常压缩状态,设计转移策略
01BFS
-
边权只有 0 和 1 ,可以看作特殊的Dijkstra
-
使用双端队列代替优先队列 ,每次从头部弹出
-
通过 0 更新距离的节点从头部进入双端队列
-
通过 1 更新距离的节点从尾部进入双端队列
-
不需要
vis[]来标记状态,证明略
双向 BFS
-
从源点,目标点同时开始
-
每次展开节点数较小的一侧
-
第一次出现交集返回答案
习题
01 经典BFS
leetcode 1162
class Solution {vector<int>mo={-1,0,1,0,-1};struct p{int x,y;};
public:int maxDistance(vector<vector<int>>& g) {int n=g.size();int sum=0;for(int i=0;i<n;++i){for(int j=0;j<n;++j){sum+=g[i][j];}}if(sum==0||sum==n*n){return -1;}vector<vector<bool>>vis(n,vector<bool>(n));queue<p>q;for(int i=0;i<n;++i){for(int j=0;j<n;++j){if(g[i][j]==1){q.push({i,j});}}}int ans=-1;while(q.size()){ans++;int siz=q.size();for(int i=0;i<siz;++i){auto [x,y]=q.front();q.pop();for(int i=0;i<4;++i){int nx=x+mo[i];int ny=y+mo[i+1];if(nx<0||ny<0||nx>=n||ny>=n)continue;if(vis[nx][ny]==0){vis[nx][ny]=1;q.push({nx,ny});}}}}return ans;}
};
02 设计状态转移
leetcode 691
class Solution {string get_next(string &cur,string &word){string nex="";int lc=cur.size();int lw=word.size();int i=0,j=0;while(i<lc&&j<lw){if(cur[i]==word[j]){i++;j++;}else if(cur[i]<word[j]){nex+=cur[i];i++;}else{j++;}}while(i<lc){nex+=cur[i++];}return nex;}
public:int minStickers(vector<string>& words, string t) {sort(t.begin(),t.end());vector<vector<string>>gra(26);for(string word:words){sort(word.begin(),word.end());int l=word.size();for(int i=0;i<l;++i){if(i==0||word[i]!=word[i-1]){gra[word[i]-'a'].push_back(word);}}}int ans=-1;queue<string>q;unordered_set<string>vis;vis.insert(t);q.push(t);while(q.size()){ans++;int siz=q.size();for(int i=0;i<siz;++i){string cur=q.front();q.pop();if(cur=="")return ans;for(string &word:gra[cur[0]-'a']){string nex=get_next(cur,word);if(vis.count(nex)==0){vis.insert(nex);q.push(nex);}}}}return -1;}
};
03 设计状态转移
leetcode 752
class Solution {
public:int openLock(vector<string>& deadends, string target) {if(target=="0000")return 0;unordered_set<string>vis;for(auto c:deadends){vis.insert(c);if(c=="0000")return -1;}unordered_set<string>q1;unordered_set<string>q2;q1.insert("0000");q2.insert(target);vis.insert("0000");vis.insert(target);int ans=0;while(!q1.empty()&&!q2.empty()){ans++;unordered_set<string>q3;for(const string&cur:q1){for(int i=0;i<4;++i){string n1=cur,n2=cur;int x=cur[i]-'0';char c1=((x+1)%10)+'0';char c2=((x-1+10)%10)+'0';n1[i]=c1;n2[i]=c2;if(q2.count(n1)!=0)return ans;if(q2.count(n2)!=0)return ans;if(vis.count(n1)==0){vis.insert(n1);q3.insert(n1);}if(vis.count(n2)==0){vis.insert(n2);q3.insert(n2);}}}q1=q3;if(q2.size()<q1.size())swap(q1,q2);}return -1;}
};
04 状态压缩
leetcode 773
class Solution {vector<vector<int>>near={{1,3},{0,2,4},{1,5},{0,4},{1,3,5},{2,4}};
public:int slidingPuzzle(vector<vector<int>>& board) {string st="";for(int i=0;i<2;i++){for(int j=0;j<3;++j){st+=to_string(board[i][j]);}}if(st=="123450")return 0;unordered_set<string>vis;unordered_set<string>q1;unordered_set<string>q2;q1.insert(st);q2.insert("123450");vis.insert(st);vis.insert("123450");int step=0;while(!q1.empty()&&!q2.empty()){step++;unordered_set<string>q3;for(const string cur:q1){vector<string>nex=get_nex(cur);for(string n:nex){if(q2.count(n)!=0)return step;if(vis.count(n)==0){vis.insert(n);q3.insert(n);}}}q1=q3;if(q2.size()<q1.size())swap(q1,q2);}return -1;}vector<string>get_nex(string cur){vector<string>ans;int z=0;while(cur[z]!='0')z++;for(int i:near[z]){string temp=cur;temp[z]=cur[i];temp[i]='0';ans.push_back(temp);}return ans;}
};
05 01BFS
leetcode 2290
class Solution {vector<int>mo={-1,0,1,0,-1};struct p{int x,y;};
public:int minimumObstacles(vector<vector<int>>& g) {int n=g.size();int m=g[0].size();vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));deque<p>q;q.push_front({0,0});dis[0][0]=0;while(q.size()){int siz=q.size();for(int i=0;i<siz;++i){auto [x,y]=q.front();q.pop_front();if(x==n-1&&y==m-1)return dis[x][y];for(int i=0;i<4;++i){int nx=x+mo[i];int ny=y+mo[i+1];if(nx<0||ny<0||nx>=n||ny>=m)continue;int nd=dis[x][y]+g[nx][ny];if(nd<dis[nx][ny]){dis[nx][ny]=nd;if(g[nx][ny]==1){q.push_back({nx,ny});}else q.push_front({nx,ny});}}}}return -1;}
};
06 01BFS
leetcode 1368
class Solution {vector<vector<int>>mo={{},{0,1},{0,-1},{1,0},{-1,0}};struct p{int x,y;};
public:int minCost(vector<vector<int>>& g) {int n=g.size();int m=g[0].size();vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));deque<p>q;q.push_front({0,0});dis[0][0]=0;while(q.size()){int siz=q.size();for(int i=0;i<siz;++i){auto [x,y]=q.front();q.pop_front();if(x==n-1&&y==m-1)return dis[x][y];for(int i=1;i<=4;++i){int nx=x+mo[i][0];int ny=y+mo[i][1];if(nx<0||ny<0||nx>=n||ny>=m)continue;int cost=i==g[x][y]?0:1;int nd=dis[x][y]+cost;if(nd<dis[nx][ny]){dis[nx][ny]=nd;if(cost==1){q.push_back({nx,ny});}else q.push_front({nx,ny});}}}}return -1;}
};
07 01BFS
leetcode 3286
class Solution {vector<int>mo={-1,0,1,0,-1};struct p{int x,y;};
public:bool findSafeWalk(vector<vector<int>>& g, int health) {int n=g.size();int m=g[0].size();vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));deque<p>q;q.push_front({0,0});dis[0][0]=g[0][0];while(q.size()){int siz=q.size();for(int i=0;i<siz;++i){auto [x,y]=q.front();q.pop_front();if(x==n-1&&y==m-1)return dis[x][y]<health;for(int i=0;i<4;++i){int nx=x+mo[i];int ny=y+mo[i+1];if(nx<0||ny<0||nx>=n||ny>=m)continue;int nd=dis[x][y]+g[nx][ny];if(nd<dis[nx][ny]){dis[nx][ny]=nd;if(g[nx][ny]==1){q.push_back({nx,ny});}else q.push_front({nx,ny});}}}}return 0;}
};
08 BFS + DFS
leetcode 126
class Solution {vector<vector<string>>ans;vector<string>path;unordered_map<string,vector<string>>gra;void dfs(string cur,string target){path.push_back(cur);if(cur==target){ans.push_back(path);}else if(gra.count(cur)){for(string nex:gra[cur]){dfs(nex,target);}}path.pop_back();}
public:vector<vector<string>> findLadders(string beginWord, string endWord, vector<string>& wordList) {unordered_set<string>words;for(string word:wordList){words.insert(word);}if(words.count(endWord)==0){return vector<vector<string>>();}unordered_set<string>curleve;unordered_set<string>nexleve;bool found=0;curleve.insert(beginWord);while(curleve.size()){for(auto x:curleve){words.erase(x);}for(auto word:curleve){string t=word;int lw=word.size();for(int i=0;i<lw;++i){char old=word[i];for(char ch='a';ch<='z';++ch){if(ch==old)continue;t[i]=ch;if(words.count(t)){if(t==endWord){found=1;}gra[t].push_back(word);nexleve.insert(t);}}t[i]=old;}}if(found)break;curleve=nexleve;nexleve.clear();}if(found){dfs(endWord,beginWord);for(auto &x:ans){reverse(x.begin(),x.end());}}return ans;}
};
09 双向BFS
leetcode 127
class Solution {
public:int ladderLength(string beginWord, string endWord, vector<string>& wordList) {unordered_set<string>words;for(auto x:wordList)words.insert(x);if(words.count(endWord)==0)return 0;unordered_set<string>small;unordered_set<string>big;unordered_set<string>nex;small.insert(beginWord);big.insert(endWord);int ans=1;while(small.size()){ans++;for(auto word:small){string t=word;for(int i=0;i<(int)t.size();++i){for(char ch='a';ch<='z';++ch){if(ch==word[i])continue;t[i]=ch;if(big.count(t))return ans;if(words.count(t)){words.erase(t);nex.insert(t);}}t[i]=word[i];}}if(nex.size()>big.size()){small=big;big=nex;}else{small=nex;}nex.clear();}return 0;}
};