[DAG算法] 拓扑排序

本文介绍了有向无环图(DAG)的概念,特别是其在表示流程图中的作用。拓扑排序是判断DAG是否能顺利进行的重要工具,通过删除入度为0的节点并更新其他节点的入度来实现。拓扑排序不仅用于判断图是否有环,还可以计算任务的最早开始时间和关键路径。以P1113杂务问题为例,展示了如何在拓扑排序过程中计算最短完成时间。
摘要由CSDN通过智能技术生成

有向无环图 DAG(directed acycline graph)

相比较无向图来说,有向图比较特殊。

有向图
看这幅图,所有的边都带上了方向,也就是说 从节点1可以到节点2,但是节点2不能通过那条边到达节点1

一般来说,有向无环图可以用来作为表示流程图的一种工具(想想流程图,是不是也是从一个任务到另一个任务或多个任务)
于是判断一个流程图是不是很够顺利进行,就有了拓扑排序。

先来看拓扑排序的代码吧。

这里建图采用链式前向星,操作复杂度比vector要快。

int topology(int n){
   
	int ans = 0;
	queue<int> q;
	for(int i = 1; i <= n; ++i){
   
		if(!in[i])	q.push(i);
	}
	while(!q.empty()){
   
		int u = q.front();	q.pop();
		Time[u] += tt[u];
		ans = max(ans,Time[u]);
		for(int i = head[u]; ~i ; i = edge[i].nxt){
   
			Edge &e = edge[i];
			Time[e.v] = max(Time[e.v],Time[u]);
			if(!(--in[e.v])) q.push(e.v);
		}
	}
	return ans;
}

为什么拓扑排序能够判断一个有向图是不是能够顺利进行而没有冲突呢?

首先,拓扑排序将入度为0的点插入队列,在这里如何去理解入度为0? -> 在一个流程图中就意思是 他没有前驱(就做这个任务前没有其他任务的前提),因此可以插入队列(也就是这个任务可以做),然后,我们要把他的所有出度的边删掉(例如u->v 删掉这条边,in[v]减1,这就说明v的任务的前置要求少了一个,当为0的时候,就又说明这个任务可以做了,于是又插入队列,最后我们只需要判断我们做的任务是不是做完了(检查所有的in[i[,或者记录做的任务数都可),如果没做完,说明这个DAG是有环的,显然有环的时候肯定不满足流程图,因为产生了矛盾。

同时我们也可以用拓扑排序去计算一个任务的最早开始时间,以及去判断DAG是否有环,并且也可以求出关键路径

例如:P1113 杂务
题意:
John的农场在给奶牛挤奶前有很多杂务要完成,每一项杂务都需要一定的时间来完成它。比如:他们要将奶牛集合起来,将他们赶进牛棚,为奶牛清洗乳房以及一些其它工作。尽早将所有杂务完成是必要的,因为这样才有更多时间挤出更多的牛奶。当然,有些杂务必须在另一些杂务完成的情况下才能进行。比如:只有将奶牛赶进牛棚才能开始为它清洗乳房,还有在未给奶牛清洗乳房之前不能挤奶。我们把这些工作称为完成本项工作的准备工作。至少有一项杂务不要求有准备工作,这个可以最早着手完成的工作,标记为杂务 1 1 1。John有需要完成的 n n n个杂务的清单,并且这份清单是有一定顺序的,杂务 k ( k > 1 ) k(k>1) k(k>

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值