有向无环图 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>