推荐学习资料:
总结:
最近花了一点点时间学了拓扑排序,感觉到图论真是神奇。
总的来说,拓扑排序的题还是有一定的灵活度的,除去一些比较水的题,很容易跟其他算法或者数据结构混在一起,一下子难度就上去了,也从单一的模板的题变为了多重模板题或者智力题。
拓扑排序比较好理解,就是建立有向图,每次取入度为0的点,去除掉与他有关的边,然后再去除。最后形成了一个拓扑序。
代码实现,可以用邻接矩阵也可以用邻接表,但是如果是稀疏图而且图又大,邻接矩阵可能会浪费一些时间。
我比较喜欢用邻接表写,因为代码写起来不容易出错,用一个队列保存当前所有入度为0的点。
toposort开始,先找出所有入度为0的点,全部push到队列q中,这些点所有的入度-1,就不再需要考虑了。
接着,开始while(!q.empty()),注意由于q中保存的是入度为0的点。一旦q.size()==0,那么也就是说当前图出现了环,循环将直接跳出。
这时可以设置一个变量cnt统计访问到的点的数量,一旦cnt!=n,也就是说没有完全访问,用这个方法可以捕捉到错误。
一旦出现环,说明单位之间的关系产生了矛盾,比如:
这些都是环。
有些题可能除了需要判断矛盾之外,还需要判断是否可以确定,也就是是否唯一。
只需要在while中加一个判断是否q.size()>1,如果大于1,说明在某一次取入度为0的时候取到了多个,这必然产生多种结果。
这只是一些最基础的总结,很多入门的水题只需要这些知识就能解决,但是大部分的题目中,拓扑排序只占了一小部分,根本不可能出一题纯拓扑排序的题目。
下面是一些题目,自己也在做,不断更新,部分题目点击题号有题解:
加粗代表重要,下划线代表只看没写。
HDU 1285 2094 2647 3342
POJ 2367
上面的都是很水的题,大部分题都是秒A,用来练手和测试用。
HDU 1811 与并查集缩点配合求解。
POJ 1094 需要绕一绕判断。
POJ 3687 这题比较重要,做法很巧,字典序最小。
POJ 1128 找出只有两个表能相互影响的点,然后在输入的表中查看覆盖的点建边。
POJ 1420 excel表计算,很容易看出可以拓扑的点,存在未知的值就把当前表达式和那个值建边,跑一边拓扑即可,但是10000KB的内存不知道网上大牛的(26×26×26+26×26+26)×1000的数组不知道怎么AC的,如果真是10000KB的话,正解应该是深搜,紫书上有类似的题。
POJ 3660 这题这题不是使用拓扑排序写的,需要确定已经完全可以确定的名次,这题想了两天都没出,其实只需要统计在点前和点后的可以连通的点的个数是n-1的点的数量即可。