我的OI心得(三)之 图论(二)

来源:互联网 发布:电脑鞋子配色软件 编辑:程序博客网 时间:2024/04/29 21:31

树与BFS

上一章我们了解了搜索树,并想办法把他给深度优先遍历了。今天就来讲BFS,即宽度优先搜索。

如下图:

 其编号就是BFS遍历的顺序——就是按层遍历。BFS将依次遍历每一层,层层推进。这有什么好处呢?如果题目要求输出一个解,就意味着找到解就退出。如果我们估计这个解的节点的层次不很深,但是各节点的子节点都很多,那么BFS在时间上显然可以占优——DFS会一直深入下去,导致大量的浪费。此外,对于求一系列状态的最优解(要求不断更新)的问题(比如单源最短路径或动态规划),BFS可以尽可能大地将子问题重叠处理,效率较DFS高相当多:DFS先解决新问题再解决老问题,但是有相当多的问题是这样的:新问题由若干老问题决定。宽搜将老问题解决后再解决新问题,可以做到一锤定音(想想拓扑排序),而深搜则需要反复迭代。

BFS的致命弱点是空间问题。我们对于每个状态都要保存,如此根本无法解决状态过复杂的问题。究其原因,其遍历顺序是不连续的,比如我做完节点5就去做节点6,而没有什么直接的措施可以将节点5的状态转换为节点6的状态——DFS则不然,他会从52再到6,沿着边用全局变量走得很爽。

 因此,BFS的价值在于充分利用空间而节省时间。在时间金贵的NOIP中,BFS还是很吃香的。

 BFS的具体实现:用队列。就是说,队首碰到新状态要做了,扔队尾去,到时候再说。

 实现如下:

t1,t2:integer;{t1表示队首,t2表示队尾}

queue:array[1..1000]of node{各题表示状态不一,此处用node表示}

t1=1;

t2=1;

queue:={根节点}

repeat

u=queue[t1];{队首元素出队}

inc(t1);

{扩展u,扩产出若干节点,t2那头}

until t1=t2;{队列为空,做完了}

 

注意:多结合哈希表!BFS入门请寻找八数码问题或某年IOI的“魔版”,其中八数码去了解下康托展开。

原创粉丝点击