拓扑排序

数据结构导论之第五章图

别等时光非礼了梦想. 提交于 2020-04-02 21:21:11
一、图的概念 图的定义 1、图 在树形结构中,结点间具有层次关系,每一层结点只能和上一层中的至多一个结点相关, 但可能和下一层的多个结点相关。而在图结构中,任意两个结点之间都可能相关,即结点之 间的邻接关系可以是任意的 图G: 是由集合V和E组成,记成G=(V,E); V 是顶点集(非空);E 是边集 (可空);边是顶点的有序对或无序对;(边反映了两顶点之间的关系) 2、有向图 : 边是顶点的有序对的图(图中每条边都用箭头指明了方向)一个具有 n 个顶点的 有向完全图的弧 数为 n(n-1) 3、无向图 : 边是顶点的无序对的图。一个具有 n 个顶点的 无向完全图的边 数为 n(n-1)/2 。 4、权、带权图: 图的边附带数值,这个数值叫权。权在实际应用中可表示从一个顶点到另一个顶点的 距离、代价或耗费等。每条边都带权的图称为带权图。 5、顶点的度、入度、出度 无向图中 顶点 v 的度是与该顶点相关联的边的数目,记为 D(v)。 如果 G 是一个有向图 ,则把以顶点 v 为终点的弧的数目称为 v 的入度,记为 ID(v); 把以顶点 v 为始点的弧的数目称为 v 的出度,记为 OD(v)。 有向图中顶点 v 的度等于入度与出度的和,即 D(v)=ID(v)+OD(v)。 6、子图: 设 G=(V,E)是一个图,若 E'是 E 的子集,V'是 V 的子集,并且 E'中的边仅与 V

Algorithm: 拓扑排序

こ雲淡風輕ζ 提交于 2020-03-30 04:01:58
摘自百度: 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若 ∈E(G),则u在线性序列中出现在v之前。 方法: 拓扑排序 方法如下: (1)从 有向图 中选择一个没有前驱(即 入度 为0)的顶点并且输出它. (2)从网中删去该顶点,并且删去从该顶点发出的全部有向边. (3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止. 例子:poj1094 解法: 摘自http://www.cnblogs.com/pushing-my-way/archive/2012/08/23/2652033.html 题意:给你一些大写字母间的偏序关系,然后让你判断能否唯一确定它们之间的关系,或者所给关系是矛盾的,或者到最后也不能确定它们之间的关系。 分析: 用拓扑排序: 1.拓扑排序可以用栈来实现,每次入栈的是入度为0的节点。 1.拓扑排序的结果一般分为三种情况:1、可以判断 2、有环出现了矛盾 3、条件不足,不能判断. 2.这道题不仅需要判断这三种情况,而且还要判断在处理第几个关系时出现前两种情况,对于本道题来说三种情况是有优先级的。前两种情况是平等的谁先出现先输出谁的相应结果,对于第三种情况是在前两种情况下都没有的前提下输出相应结果的. 网上对于这道题的错误提示: 1.本题顺序: a

拓扑排序详解

十年热恋 提交于 2020-03-30 02:03:37
拓扑排序看起来很难,其实了解后不算难(思想非常清楚) 关键掌握思想后需要学会应用到具体的题目中去。(从入度为0到出度为0) 1、拓扑排序的介绍 对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。 拓扑排序对应施工的流程图具有特别重要的作用,它可以决定哪些子工程必须要先执行,哪些子工程要在某些工程执行后才可以执行。为了形象地反映出整个工程中各个子工程(活动)之间的先后关系,可用一个有向图来表示,图中的顶点代表活动(子工程),图中的有向边代表活动的先后关系,即有向边的起点的活动是终点活动的前序活动,只有当起点活动完成之后,其终点活动才能进行。通常,我们把这种顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network),简称AOV网。 一个AOV网应该是一个有向无环图,即不应该带有回路,因为若带有回路,则回路上的所有活动都无法进行(对于数据流来说就是死循环)。在AOV网中,若不存在回路,则所有活动可排列成一个线性序列,使得每个活动的所有前驱活动都排在该活动的前面,我们把此序列叫做拓扑序列(Topological order),由AOV网构造拓扑序列的过程叫做拓扑排序

P4017 最大食物链计数(拓扑排序+邻接矩阵(表))

孤街醉人 提交于 2020-03-30 01:47:00
题目背景 你知道食物链吗?Delia 生物考试的时候,数食物链条数的题目全都错了,因为她总是重复数了几条或漏掉了几条。于是她来就来求助你,然而你也不会啊!写一个程序来帮帮她吧。 题目描述 给你一个食物网,你要求出这个食物网中最大食物链的数量。 (这里的“最大食物链”,指的是 生物学意义上的食物链 ,即 最左端是不会捕食其他生物的生产者,最右端是不会被其他生物捕食的消费者) 输入格式 第一行,两个正数n、m,表示生物种类n和吃与被吃的关系数m。 接下来m行,每行两个正数,表示被吃的生物A和吃A的生物B。 输出格式 一行一个整数,为最大食物链数量模上80112002的结果。 输入输出样例 输入 #1 5 7 1 2 1 3 2 3 3 5 2 5 4 5 3 4 输出 #1 5 说明/提示 各测试点满足以下约定: 【补充说明】 数据中不会出现环,满足生物学的要求。 时间限制1s,结果模上80112002. 思路:    此题所找的是总食物链的长度,实际上翻译过来就是找到所有入度为0对应出度为0的链的长度,这一思想恰好满足拓扑排序的性质(具体拓扑排序见另一篇帖子)。因此此处首先采用邻接矩阵+拓扑排序的方法去实现(别用dfs效率太低,基本的不剪枝的只过两个测试点) 实现代码(邻接矩阵): 1 #include<bits/stdc++.h> 2 using namespace std; 3

hdu1532 用BFS求拓扑排序

早过忘川 提交于 2020-03-26 23:45:23
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1285 题目给出一些点对之间的先后顺序,要求给出一个字典序最小的拓扑排列。对于拓扑排序的问题,我们有DFS和BFS都能够解决,但是问题是DFS只能处理上一层结点和下一层结点相对于根节点之间的距离,也就是说深度就是他们之间的先后顺序,对于同一层的,是没有先后顺序的,但是BFS可以处理同一层之间的先后关系,所以我们考虑用BFS进行遍历,并且将原始BFS求拓扑排序中的队列变成优先队列。这样我们就能在每一层中优先选择字典序小的结点先输出。 代码如下: 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ui; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define pf printf 7 #define mem(a,b) memset(a,b,sizeof(a)) 8 #define prime1 1e9+7 9 #define prime2 1e9+9 10 #define pi 3.14159265 11 #define lson l,mid,rt<<1 12 #define rson mid+1,r,rt<<1|1

算法:强连通分量缩点

别来无恙 提交于 2020-03-26 13:21:55
有时对于一个有向图我们及其渴望将其变为一个有向无环图,这样我们就要用到强连通分量缩点了。 例题 洛谷3387 缩点 题目背景 缩点+DP。 题目描述 给定一个 n个点 m条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。 输入格式 第一行两个正整数n,m。 第二行n个整数,依次代表点权。 第三至(m + 2)行,每行两个整数u,v,表示一条u -> v的有向边。 输出格式 共一行,最大的点权之和。 输入输出样例 输入 2 2 1 1 1 2 2 1 输出 2 说明/提示 对于 100%的数据,1 <= n <= 10^4,1 <= m <= 10^5,0 <= 点权 <= 10^3。 强连通分量缩点 对于一道图论题,有时我们会发现如果说这是一个有向无环图会很好解决,但题目中却并没有说无环,这时我们希望将这个有向图变成一个有向无环图,这就要用到强连通分量缩点了。 在一个强连通分量中,我们知道任意两个点可以互相到达,那么其实我们就可以利用这个特点去对其进行缩点,将原图变成一个有向无环图。 在做tarjan算法时,我们已经对每个点进行了染色,所以这样缩点就很简单了,如果一条边起点u和终点v的颜色不一样,就以u的颜色color[u]为起点、v的颜色color[v]为终点建一条边。

题解 拓扑排序 POJ 1094

本秂侑毒 提交于 2020-03-22 08:09:52
题意:给你一些大写字母间的偏序关系,然后让你判断能否唯一确定它们之间的关系,或者所给关系是矛盾的,或者到最后也不能确定它们之间的关系。 分析: 用拓扑排序: 1.拓扑排序可以用栈来实现,每次入栈的是入度为0的节点。 1.拓扑排序的结果一般分为三种情况:1、可以判断 2、有环出现了矛盾 3、条件不足,不能判断. 2.这道题不仅需要判断这三种情况,而且还要判断在处理第几个关系时出现前两种情况,对于本道题来说三种情况是有优先级的。前两种情况是平等的谁先出现先输出谁的相应结果,对于第三种情况是在前两种情况下都没有的前提下输出相应结果的. 网上对于这道题的错误提示: 1.本题顺序: a.先判有没有环,有环就直接输出不能确定; b.如果没有环,那么就看会不会有多种情况,如果有多种情况就再读下一行;如果全部行读完还是有多种情况,就是确定不了; c.如果最后没有环,也不存在多种情况(即每次取出来入度为零的点只有一个),那么才是答案; 2.有答案就先出答案,不管后面的会不会矛盾什么的; 3.如果在没有读完所有输入就能出答案,一定要把剩下的行都读完。 代码 #include <iostream> #include <cstdio> #include <string.h> #include <stack> using namespace std; const int MAX=27; int graph

hdu 4857 逃生 拓扑排序

十年热恋 提交于 2020-03-20 18:24:59
逃生 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4857 Description 糟糕的事情发生啦,现在大家都忙着逃命。但是逃命的通道很窄,大家只能排成一行。 现在有n个人,从1标号到n。同时有一些奇怪的约束条件,每个都形如:a必须在b之前。 同时,社会是不平等的,这些人有的穷有的富。1号最富,2号第二富,以此类推。有钱人就贿赂负责人,所以他们有一些好处。 负责人现在可以安排大家排队的顺序,由于收了好处,所以他要让1号尽量靠前,如果此时还有多种情况,就再让2号尽量靠前,如果还有多种情况,就让3号尽量靠前,以此类推。 那么你就要安排大家的顺序。我们保证一定有解。 Input 第一行一个整数T(1 <= T <= 5),表示测试数据的个数。 然后对于每个测试数据,第一行有两个整数n(1 <= n <= 30000)和m(1 <= m <= 100000),分别表示人数和约束的个数。 然后m行,每行两个整数a和b,表示有一个约束a号必须在b号之前。a和b必然不同。 Output 对每个测试数据,输出一行排队的顺序,用空格隔开。 Sample Input 1 5 10 3 5 1 4 2 5 1 2 3 4 1 4 2 3 1 5 3 5 1 2 Sample Output 1 2 3 4 5 Hint 题意 题解: 反着做

拓扑排序及其实际应用

此生再无相见时 提交于 2020-03-15 13:17:53
  最近在做实际项目中遇到了一个问题,如何判断一个层级结构的图是否存在循环引用。刚开始想到了方法是用递归进行判断,后来想到大学学过的拓扑排序可以解决该问题,于是翻了下数据结构这本书,阅读了园友的文章,根据自己的理解写下了这篇随笔。 阅读目录 拓扑排序介绍 问题引入及算法实现 本章总结 回到顶部 拓扑排序介绍   百度百科定义:   对一个 有向无环图 (Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个 偏序 得到该集合上的一个 全序 ,这个操作称之为拓扑排序。   上面的定义看完可能不知道是什么意思,举两个实际的例子就明白了。 1.大学课程排序    大学课程的学习是有先后顺序的,C语言是基础,数据结构依赖于C语言,其它课程也有类似依赖关系。这样的一个课程安排是怎么实现的呢?   2.VS项目编译顺序 假设VS中有三个项目A,B,C,它们的关系如下图。VS编译器是如何判断三个项目的编译顺序的呢? 回到顶部 问题引入及算法实现   这次实际项目中碰到的问题可以归纳为控件联动选择,即常见的省份,城市,地区联动

拓扑排序

爱⌒轻易说出口 提交于 2020-03-09 12:15:51
拓扑排序是针对有向无环图的,当然也可以用它来检测到底有没有环,数据结构中学过其构成原理,这里就不再赘述,主要来讲他的实现。 分析原理,其实他的过程有点类似于层次遍历,所以用队列存储入度为0的点是OK的,但其实只要每次入队的结点入度为0,也没有顺序要求,栈也行,这里我为了避免每次比较麻烦,直接用优先队列实现。 # include <iostream> # include <vector> # include <queue> # include <algorithm> using namespace std ; int G [ 51 ] [ 51 ] ; int indegree [ 51 ] = { 0 } ; int num [ 51 ] ; //存储拓扑排序顺序 struct cmp { bool operator ( ) ( const int a , const int b ) const { return indegree [ a ] > indegree [ b ] ; } } ; bool topologicalsort ( int n ) { priority_queue < int , vector < int > , cmp > q ; //优先队列存储入度下标,按从小到大排序 for ( int i = 1 ; i <= n ; i ++ ) //全部入队 q