拓扑排序
基础
拓扑排序,一般指在一个 DAG (有向无环图)中将顶点排序,使得对于图上任意一条有向边 ( u , v ) (u,v) (u,v), u u u 在拓扑排序后在 v v v 的前面。这个排序的结果称为拓扑序。显然拓扑序一般不唯一。
因为拓扑序满足后面的点不会对前面的点产生依赖,所以经常和动态规划结合在一起使用,保证后面的点不会影响前面已经计算过贡献的点。一张图存在拓扑序,当且仅当这是张 DAG,所以一个常见的套路就是:先对原图进行缩点,然后用拓扑+动态规划等统计答案。
拓扑算法基本流程:记录图中每个点的入度 d d d,将入度等于 0 0 0 的点入队。每次取出一个队首 u u u,将每一个与 u u u 相连的点 v v v 的入度减一(相当于从图中删除 u u u 和与其相连的出边)。如果 d v = 0 d_v=0 dv=0,则 v v v 也入队。一直重复到队列为空。时间复杂度 O ( n + m ) O(n+m) O(n+m),其中 n n n 为点数, m m m 为边数。
vector<int> mp[maxn];
int d[maxn],n,ans[maxn],tot;
bool toposort() {
queue<int> q;
for (int i = 1;i <= n;i ++)
if (d[i] == 0) q.push(i);
int u;
while (!q.empty()) {
u = ans[++ tot] = q.front(); q.pop();
for (auto v : mp[u])
if (--d[v] == 0) q.push(v);
}
return tot == n; // 判断是否有环,有则返回 True
}
一个最典型的应用就是对一个 AOV 网判断是否有若干个活动组成了环。AOV 网就是一张有向图,顶点表示活动,边表示活动之间进行的顺序。如果原图存在环,则最后的拓扑序不会包含所有的结点。利用这个性质就可以用来判环。
另一个应用就是计算一个 AOE 网的关键路径的长度。AOE 网与 AOV 网类似,只是边有了边权(时间),且一条边代表一个活动,而点代表一个事件;关键路径是指从起点到终点的最长路径。我们可以在拓扑的过程中用动态规划求解。记 f u f_u fu 表示触法 u u u 这个事件的最晚时间。假设当前从队列中取出 u u u,与其相连的是点 v v v,边权为 w w w,则 max ( f u + w , f v ) → f v \max(f_u+w,f_v)\to f_v max(fu+w,fv

最低0.47元/天 解锁文章
1389

被折叠的 条评论
为什么被折叠?



