广度优先搜索(BFS)(队列实现),用于求解最短路径,一般给出路径最小值,可以被形象的描述为“浅尝辄止”,具体一点就是每个顶点只访问它的邻接节点(如果它的邻接节点没有被访问)并且记录这个邻接节点,当访问完它的邻接节点之后就结束这个顶点的访问。
广度优先用到了“先进先出”队列,通过这个队列来存储第一次发现的节点,以便下一次的处理;而对于再次发现的节点,我们不予理会——不放入队列,因为再次发现的节点:
- 无非是已经处理完的了;
- 或者是存储在队列中尚未处理的。
深度优先搜索(DFS)(栈类实现),可以被形象的描述为“打破沙锅问到底”,具体一点就是访问一个顶点之后,我继而访问它的下一个邻接的顶点,如此往复,直到当前顶点一被访问或者它不存在邻接的顶点。
同样,算法导论采用了“聪明的做法”,用三种颜色来标记三种状态。但这三种状态不同于广度优先搜索:
- WHITE 未访问顶点
- GRAY 一条深度搜索路径上的顶点,即被发现时
- BLACK 此顶点的邻接顶点被全部访
两个算法都是O(V+E),在用到的时候适当选取。在使用白灰黑标志的时候,突然明白了如何用深度优先搜索来判断有向图中是否存在环。
深度优先和广度优先各有各的优缺点:
- 广优的话,占内存多,能找到最优解,必须遍历所有分枝. 广优的一个应用就是迪科斯彻单元最短路径算法.
- 深优的话,占内存少,能找到最优解(一定条件下),但能很快找到接近解(优点),可能不必遍历所有分枝(也就是速度快), 深优的一个应用就是连连看游戏.
在更多的情况下,深优是比较好的方案。
DFS:
void dfs(int p,const int end,int dist,int weit){
if(p==end){
if(dist<mind){
cnt = 1;
mind=dist;
maxt = weit;
}else if(dist==mind){
++cnt;
if(maxt<weit){
maxt = weit;
}
}
return;
}
int i;
if(dist>mind)return;//这个地方不剪枝的话最后一个case过不去
for(i=0;i<n;++i){
if(visit[i]==0 && map[p][i]!=INT_MAX){
visit[i] = 1;
dfs(i,end,dist+map[p][i],weit+wei[i]);
visit[i] = 0;
}
}
}