1. 拓扑排序算法精解与实战应用
拓扑排序是图论中一种重要的线性排序算法,它能够将有向无环图(DAG)的所有顶点排成一个线性序列,使得对于图中的每一条有向边 (u, v),u 在序列中总是位于 v 的前面。这种排序方式在任务调度、依赖关系处理等场景中有着广泛的应用。
1.1 拓扑排序的核心思想
拓扑排序的核心在于不断选择入度为0的顶点并移除其出边,直到所有顶点都被处理或发现图中存在环。这种"剥洋葱"式的处理方式确保了依赖关系的正确性。在实际编码中,我们通常使用两种实现方式:
- BFS实现(Kahn算法):通过维护入度数组和队列,每次处理入度为0的顶点
- DFS实现:利用深度优先搜索的完成时间逆序排列
提示:当图中存在环时,拓扑排序无法完成,这也是检测有向图是否存在环的有效方法。
1.2 典型问题解析:LGP1347排序
原题要求根据一系列不等式关系确定字母的排序顺序。这个问题可以转化为拓扑排序问题,其中每个不等式A<B对应图中的一条有向边A→B。
巧妙解法:采用二分答案结合传递闭包的方法。二分确定能够形成有效排序的关系数量,检查时:
- 构建前mid个关系形成的有向图
- 计算传递闭包判断是否存在环或完全确定顺序
- 根据检查结果调整二分边界
cpp复制int check(int x){
memset(d, 0, sizeof(d));
for(int i=0; i<x; i++) d[e[i].first][e[i].second] = 1;
// Floyd-Warshall计算传递闭包
for(int k=1; k<=n; k++)
for(int i=1; i<=n; i++)
for(int j=1; j<=n; j++)
d[i][j] |= (d[i][k] & d[k][j]);
// 检查环和完全排序
int sum = 0;
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
sum += d[i][j];
i
