算法复习——拓扑排序
板子
inline void topsort()
{
queue<int>q;
for(int i=1;i<=n;i++)
if(!deg[i]) q.push(i);
while(!q.empty())
{
int x=q.front();q.pop();
top[++pos]=x;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;deg[y]--;
//dp递推
if(!deg[y]) q.push(y);
}
}
}
1.性质
1-1.性质1
在DAG中,对于任何的点 iii到 jjj 的有向边,定义点 iii 的拓扑序为 tit_iti ,点 jjj 的拓扑序为 tjt_jtj ,满足 ti<tjt_i<t_jti<tj。
1-2.性质2
在DAG中,图的拓扑序唯一,当且仅当它的拓扑层数与点数相等。
拓扑层数——BFS层数,可以理解为图中最长链的长度,最简情况下为链
1-3.性质3
在DAG中,如果点 iii 有一段到达点 jjj 的路径,定义点 iii 的拓扑序为 tit_iti ,点 jjj 的拓扑序为 tjt_jtj ,满足 ti<tjt_i<t_jti<tj。(反之不一定成立,性质4为反例)
1-4.性质4
一个DAG中,点 jjj 为满足 ti<tjt_i<t_jti<tj,且 iii 有一条指向 jjj 的边时,tjt_jtj 最小的点,
则对于任意一个拓扑序在 tit_iti 与 tjt_jtj 的区间内的点 ppp,点 iii 与点 ppp 之间没有路径,即点 iii 一定不能到达点 ppp 。
证明:反证法。如果存在一个点kkk,满足 ti<tk<tjt_i<t_k<t_jti<tk<tj 且点 iii 可到达 kkk,则两者的路径上存在一点 qqq,满足点 qqq 为从点 iii 为起点,点 kkk 为终点的路径上的第一个点,则其与iii 间存在一条边。由拓扑序的基本定义可得tj≤tqt_j \leq t_qtj≤tq。而因为点 qqq 有一条可到达点 kkk 的路径,由拓扑序的拓展性质1可得 tq<tkt_q<t_ktq<tk , 推出 tj<tkt_j<t_ktj<tk ,与假设不符,故原命题正确。
2.应用
2-1.用于递推过程的遍历顺序
- 在DAG中,用拓扑序求最短路,最长路,可做到O(n)O(n)O(n)复杂度
2-2.判断图中是否有环
在没有DAG保证的图中运行一遍拓扑排序,如果拓扑序中的点数小于图的总点数,即有环,否则为DAG。
其中,拓扑序中的点的个数与总点数的差即为所有环的总点数
正确性证明:在图中有环的情况下,环中每个点在被遍历到时的入度均不为0,无法入队,无法被拓扑序记录。
2-3.利用性质处理图中可达性问题
性质如上