拓扑排序

拓扑排序&关键路径

前言

今天开始学习拓扑排序和关键路径,写个博客记录一下qwqphp

目录

  • 知识讲解html

  • 题目模型node

  • 算法框架c++

  • 例题讲解算法

  • 习题推荐网络


知识搬运

在介绍拓扑排序以前,咱们来引入一下框架

  • 有向无环图

顾名思义,若是一个有向图的任意顶点都没法经过一些有向边回到自身,那么就称这个图为有向无环图(DAG)ide

  • 拓扑序列

为了能更好地理解拓扑排序是什么,咱们先经过一个栗子来感觉一下:学习

若是你想说一口流利的英语,那你须要先学英语口语

若是你想学英语口语,那你须要多读英语文章

若是你想读英语文章,那你须要学习不少英语单词

综上,你能说一口流利英语的全过程以下(一本正经 ):spa

学习英语单词->多读英语文章->锻炼英语口语->流利的英语

这样的一个顺序序列就是拓扑序列

  • 拓扑排序

简单来讲,求得如上拓扑序列的过程就叫作拓扑排序

说得完整一点:将有向无环图\(G\)的全部顶点排成一个线性序列,使得对图\(G\)中的任意两个顶点\(u\)\(v\),若是存在一条边\(<u,v>\),那么在这个线性序列中,\(u\)必定在\(v\)的前面的过程就叫作拓扑排序

  • 做用&补充
  1. 由于单个任务之间可能存在多个并列关系,因此拓扑序列并非惟一的

  2. 若是图\(G\)中存在环,那么拓扑排序后获得的序列元素个数将不等于原始元素个数\(N\),因此咱们能够经过这个特色去判断一个图是否有环

  3. 生活中许多大型项目都是分步骤完成的,因此拓扑排序能够说是对此应运而生,经过求拓扑序列能够肯定每一个子任务的最先完成时间和最晚完成时间(也能够求得图\(G\)最长路径

  4. 其实拓扑排序更多地是和其余算法搭配使用,解决的问题也更复杂,因此必定要理解到拓扑排序的实质,不能只懂表面

  • 关键路径

这个内容吧..说实话感受就是提炼出的两种模型:\(AOV\)网和\(AOE\)

拓扑排序加点其余算法就能搞定,就不细讲了(多是我理解错误,欢迎你们指出)


题目模型

给定\(N\)个子任务以及任务之间的前后关系(能够推得并列关系)

  1. 要求解决整个问题的最短期

  2. 要求求出每一个子任务的最先开始时间

  3. 要求求出每一个子任务的最晚完成时间

算法框架

  1. 在输入边时,存储并统计每一个点的入度

  2. 全部入度为0的点装入一个队列(能够是普通队列,也能够是优先队列,主要看题目需求)

  3. 从队列中取出对首元素\(x\),遍历全部与\(x\)相连的点\(v\),再将\(v\)的入度减一,若是减后\(v\)的入度变为0,则将\(v\)也入队

  4. 重复3的操做直到队列为空

最终的拓扑序列就是取出的\(x\)的顺序


例题讲解

纯纯的板子题,不过题目有点坑,必需要用\(stack\)才能经过(题目要求..大雾)

本题是多组数据啊,其余的也就是板子题了,多刷点这种无脑题板子就敲熟了

来挂一发板子(使用链式前向星存图,固然\(vector\)也行啊):

#include <bits/stdc++.h>
using namespace std;
queue<int> q;
vector<int> ans;
int n,m,u,v,tot;
int in[510005],head[510005];

struct node {
	int to,net;
} e[510005];

inline void add(int u,int v) {
	e[++tot].to=v;
	e[tot].net=head[u];
	head[u]=tot;
}

int main() {
	scanf("%d%d",&n,&m);
	for(register int i=1;i<=m;i++) {
		scanf("%d%d%d",&u,&v);
		add(u,v);
		in[v]++;
	}
	for(register int i=1;i<=n;i++) {
		if(in[i]==0) q.push(i);
	}
	while(!q.empty()) {
		int x=q.front();
		q.pop();
		ans.push_back(x);
		for(register int i=head[x];i;i=e[i].net) {
			int v=e[i].to;
			in[v]--;
			if(in[v]==0) q.push(v);
		}
	}
	if(ans.size()==n) {
		for(register int i=0;i<ans.size();i++) printf("%d\n",ans[i]);
	}
	else puts("ERROR");
	return 0;
}

习题推荐

(stO 洛谷好啊 Orz)

  1. 求最长路径除了可以使用拓扑排序求关键路径外,还能够取巧:

将边权所有取相反数,将问题转换为求解最短路!

那么咱们就可以用\(SPFA\)之类的算法轻松A掉(\(Dijkstra\)固然不能用啦,由于有负权)

  1. 这里贴一下同桌dalao关于菜肴制做的题解

本题虽然是一道紫色的题,可是真的挺模板啊,感受比车站分级、神经网络什么的简单多了

  1. 这里再贴一发个人关于病毒Virus的题解
相关文章
相关标签/搜索
本站公众号
   欢迎关注本站公众号,获取更多信息