开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第1天,点击查看活动详情
DFS与BFS
DFS与BFS,也就是深度优先搜索和广度优先搜索,是两种最为常见的搜索方式,它们大量被用于枚举、模拟、图论、数论等题型之中
朴素DFS
有别于一些特殊的DFS,这里介绍的是最为基本普通的DFS,在考虑DFS时,我们的思路就是,选准一条路一直走,走不通了就返回找新的能走的路,DFS运用了递归,因此画递归树也是不错的分析手段
算法伪代码:
DFS变化较多,一般不好总结出一种通用的模板,只能是以伪代码形式呈现
返回类型 dfs(需要的参数[一般写起点、枚举状态这些]){
if(终止条件[一般是越界、已经访问等等]){
//TO-DO
return XXX;
}
//这里枚举所有情况
//对同等级的枚举产生影响时,可以回溯
}
例题:
HDU-1241 Oil Deposits
AC Code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#include<algorithm>
#include<bitset>
#include<sstream>
#define range(i,a,b) for(int i=a;i<b;i++)
#define deran(i,b,a) for(int i=b;i>=a;i--)
using namespace std;
typedef priority_queue<int,vector<int>,greater<int> > gpq;
typedef priority_queue<int,vector<int>,less<int> > lpq;
typedef pair<int,int> pii;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e3+10;
int n,m;
char g[maxn][maxn];
bool st[maxn][maxn];
int dir[8][2]={{-1,0},{0,1},{1,0},{0,-1},{-1,-1},{1,1},{1,-1},{-1,1}};
void dfs(int x,int y){
if(st[x][y]){
return;
}
st[x][y]=1;
for(int i=0;i<8;i++){
int dx=x+dir[i][0];
int dy=y+dir[i][1];
if(dx>=0&&dx<n&&dy>=0&&dy<m&&!st[dx][dy]&&g[dx][dy]=='@'){
dfs(dx,dy);
}
}
}
int main(){
while(cin>>n>>m){
if(m==0||n==0){
break;
}
int ans=0;
memset(st,0,sizeof st);
for(int i=0;i<n;i++){
cin>>g[i];
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(!st[i][j]&&g[i][j]=='@'){
dfs(i,j);
ans++;
}
}
}
cout<<ans<<endl;
}
return 0;
}
朴素BFS
同样区别于特殊的BFS,本文介绍的是最为普通的BFS,在考虑BFS时,我们总是一层一层地完成选择,正如水波一般扩展,我们一般用队列来实现这一点,对于一些递归层数比较大的题,DFS容易爆栈,此时就需要BFS
算法伪代码:
BFS变化较多,一般不好总结出一种通用的模板,只能是以伪代码形式呈现
返回值类型 bfs(参数[一般填起点、开始情况]){
queue<类型>q;
//也可以像下面这样模拟队列
类型 q[N];
int hh=0,tt=-1;
vis[起点]=true;
//下面的while如果以另一种方式则是while(hh<=tt)
while(q.size()){
auto u=q.front();//auto u=q[hh++];
q.pop();
//下面枚举下一层合理的情况并加入队列
}
}
例题:
The Berland road network consists of n cities and of m bidirectional roads. The cities are numbered from 1 to n, where the main capital city has number n, and the culture capital — number 1. The road network is set up so that it is possible to reach any city from any other one by the roads. Moving on each road in any direction takes the same time.
All residents of Berland are very lazy people, and so when they want to get from city v to city u, they always choose one of the shortest paths (no matter which one).
The Berland government wants to make this country's road network safer. For that, it is going to put a police station in one city. The police station has a rather strange property: when a citizen of Berland is driving along the road with a police station at one end of it, the citizen drives more carefully, so all such roads are considered safe. The roads, both ends of which differ from the city with the police station, are dangerous.
Now the government wonders where to put the police station so that the average number of safe roads for all the shortest paths from the cultural capital to the main capital would take the maximum value.
Input
The first input line contains two integers n and m (2 ≤ n ≤ 100, ) — the number of cities and the number of roads in Berland, correspondingly. Next mlines contain pairs of integers vi, ui (1 ≤ vi, ui ≤ n, vi ≠ ui) — the numbers of cities that are connected by the i-th road. The numbers on a line are separated by a space.
It is guaranteed that each pair of cities is connected with no more than one road and that it is possible to get from any city to any other one along Berland roads.
Output
Print the maximum possible value of the average number of safe roads among all shortest paths from the culture capital to the main one. The answer will be considered valid if its absolute or relative inaccuracy does not exceed 10 - 6.
Examples
Input
4 4
1 2
2 4
1 3
3 4
Output
1.000000000000
AC Code:
#include<iostream>
#include<cstdio>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<stack>
#include<ctime>
#include<algorithm>
#include<bitset>
#include<sstream>
#define range(i,a,b) for(int i=a;i<b;i++)
#define deran(i,b,a) for(int i=b;i>=a;i--)
using namespace std;
typedef priority_queue<int,vector<int>,greater<int> > gpq;
typedef priority_queue<int,vector<int>,less<int> > lpq;
typedef pair<int,int> pii;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int N=100+10;
int used[N];
vector<int>a[N];
ll c[2][N];
ll d[2][N];
int m,n;
void bfs(int id,int s){
queue<int>q;
d[id][s] = 0;
c[id][s] = 1;
memset(used,0,sizeof(used));
q.push(s);
used[s] = 1;
int u,v;
while(!q.empty()){
u = q.front();
q.pop();
for(int i = 0;i < a[u].size();i++){
v = a[u][i];
if(!used[v]){
used[v] = 1;
d[id][v] = d[id][u]+1;
c[id][v] = c[id][u];
q.push(v);
}
else if(d[id][v] == d[id][u] + 1){
c[id][v] += c[id][u];
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
int u,v;
for(int i = 0;i <m;i++){
cin>>u>>v;
a[u].push_back(v);
a[v].push_back(u);
}
bfs(0,1);
bfs(1,n);
double ans = 1.0;
for(int i = 2;i < n;i++){
if(d[0][i] + d[1][i] == d[0][n]){
ans = max(ans,2.0*(c[0][i]*c[1][i])/ c[0][n]);
}
}
cout<<setprecision(12)<<fixed<<ans<<endl;
return 0;
}