拓扑排序
来源:互联网 发布:mac如何拷贝文件到u盘 编辑:程序博客网 时间:2024/05/30 23:33
拓扑排序的理解:
拓扑排序的定义:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。(from:百度百科)。
首先理解排序的规则:即若存在一条有向边从u到v,则在排序后的顺序里u在v的前面。并且每个点在这个拓扑序里只能出现一次。考虑为什么必须是有向无环图,首先无向显然是不行的,而如果存在环,则会存在冲突的前后关系。
对于这样一张图显然我们根据定义可得其拓扑序为:{1,2,4,3,5}。但是对于下面这张:
那么v2,v3谁在前面了?答案是都可以。于是有了两种拓扑序:{v1,v2,v3,v4}或{v1,v3,v2,v4}。
这就涉及到所谓的偏序和全序:大概理解就是偏序:存在不确定的关系(两个点没有明确的先后关系,如第二张图),全序:任意定点均存在确定关系(有唯一的先后关系,如第一张图)。全序相当于是一种特殊的偏序。
于是我们可以知道,一个有向无环图可以有一个或多个拓扑排序序列,通常顺序会取决于我们求解的过程。
拓扑排序的解法:
方法1:寻找入度为0的点
1、读入时记录每个点的入度。
2、遍历出所有入度为0的点,加入队列。
3、从队列里依次选择一个点,删除它的所有出边,将边连向的点入度减1。
4、执行3操作时判断入度减1后是否入度变为0,如果入度为0,加入队列。
5、重复执行3、4操作至所有点全部被处理。
如图:
关键代码:
for(int i=1;i<=n;i++) if(du[i]==0) q.push(i);while(!q.empty()) { int u=q.front(); q.pop(); //printf("%d ",u);在这个时候输出要求的拓扑序 for(int e=first[u];e;e=nxt[e]) { du[to[e]]--; if(du[to[e]]==0) q.push(to[e]); } }
方法2:dfs
其实就是在dfs的时候,对于一个点,在返回上一个调用处时,将其加入一个数组。最后答案就是这个数组的逆序。考虑正确性,对于一个点v,它将指向许多点,当这些点已经处理完后,v将返回上一个指向它的点的u,因为v指向的点必然在其后面,而u必然在它前面,所以依次加入他们是符合拓扑序的,只不过是逆序的。
关键代码:
void dfs(int u){ for(int e=first[u];e;e=nxt[e]) if(vis[to[e]]==false) { vis[to[e]]=true; dfs(to[e]); } ans[++num]=u;//注意答案是这个数组的逆序}int main(){ for(int i=1;i<=n;i++) if(vis[i]==false) { vis[i]=true; dfs(i); } }
bfs也是可以的,就不写了,懒>_<。
模板例题:http://blog.csdn.net/qianguch/article/details/77412866
本文有两张图片来自一篇博文:http://blog.csdn.net/lisonglisonglisong/article/details/45543451
其余来自百度图片。
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 【拓扑排序】
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 拓扑排序
- 跨域问题解决(一):tamcat下的配置
- wamp安装配置问题
- Git十周岁之际,Linus Torvalds大谈Git开发故事
- 【Two Sum】 --MyLeetCode(一)
- 图像边界识别梯度与热度关系
- 拓扑排序
- VMware虚拟机通过主机代理上网
- tomcat配置阿里druid,基于容器管理JNDI数据源
- Xenial(Ubuntu:16.04) 修改MAC地址
- iSCSI远程块存储
- Vuejs组件之slot内容分发实例详解
- CSS3自定义滚动条样式
- Java中的四种内部类
- caffe中solver.prototxt参数说明