1.AOV与DAG

活动网络可以用来描述生产计划、施工过程、生产流程、程序流程等工程中各子工程的安排问题。

 
一般一个工程可以分成若干个子工程,这些子工程称为活动(Activity)。完成了这些活动,整个工程就完成了。例如下图的代表的计算机专业课程,学习就是一个工程,每门课程的学习就是整个工程中的一个活动。
 
我们可以用上图的有向图来表示课程之间的先修关系。在这种有向图中,顶点表示课程学习活动,有向边表示课程之间的先修关系。例如顶点C1到C8有一条有向边,表示课程C1必须在课程C8之前先学习完。
 
实际上,在这种有向图中,用顶点表示活动,用有向边表示活动u必须先于活动v进行。这种有向图叫做活动网络(Activity on Vertices),记做AOV网络。
 
前驱与后继:在AOV网络中,如果存在有向边,则称活动u必须在活动v之前进行,并称u是v的直接前驱,v是u的直接后继。如果存在有向路径,则称u是v的前驱,v是u的后继。
 
有向环与有向无环图:从前驱与后继的传递性和反自反性可以看出,AOV网络中不能出现有向回路(或称为有向环)。不含有向回路的有向图称为有向无环图(DAG, Directed Acyclic Graph)。
 
在AOV网络中如果出现了有向回路,则意味着某项活动以自己作为先决条件,这是不对的。
2.拓扑排序
 
判断有向无环图的方法是对AOV网络构造它的拓扑有序序列。即将各个顶点排列成一个线性有序的序列,使得AOV网络中所有存在的前驱和后继关系都能得到满足。
 
这种构造AOV网络全部顶点的拓扑有序序列的运算称为拓扑排序(Topological Sorting)。
 
如果通过拓扑排序能将AOV网络的所有顶点都排入一个拓扑有序的序列中,则该AOV网络中必定不存在有向环;相反,如果得不到所有顶点的拓扑有序序列,则说明该AOV网络中存在有向环,此AOV网络所代表的工程是不可行的。
 
例如对上图所示的学生选课工程图进行拓扑排序,得到的拓扑有序序列为:
 
C1,C2,C3,C4,C5,C6,C8,C9,C7
或者
C1,C8,C9,C2,C5,C3,C4,C7,C6 
 
由此可见,AOV网络的拓扑有序序列可能不唯一。
 
3.Kahn算法拓扑排序算法:

(1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它;
(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边;
(3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止。
 
输入:
6 8
1 2
1 4
2 6
3 2
3 6
5 1
5 2
5 6
6 8
1 3
1 2
2 5
3 4
4 2
4 6
5 4
5 6
输出:
Great! There is not cycle.
5 1 4 3 2 6
Network has a cycle!
 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<sstream>
#include<functional>
using namespace std;
typedef long long ll;
const int maxn = + ;
const int INF = 1e9 + ;
int T, n, m, cases;
vector<int>Map[maxn];
int Count[maxn];
void topo()
{
stack<int>s;//存储入度数为0的顶点
vector<int>v;//存取拓扑排序的答案
for(int i = ; i <= n; i++)//下标从1开始
if(Count[i] == )s.push(i);
while(!s.empty())
{
int now = s.top();
v.push_back(now);
s.pop();
for(int j = ; j < Map[now].size(); j++)
{
if((--Count[Map[now][j]]) == )
{
s.push(Map[now][j]);
}
}
}
if(v.size() != n)cout<<"Network has a cycle!"<<endl;
else
{
cout<<"Great! There is not cycle."<<endl;
for(int i = ; i < v.size(); i++)cout<<v[i]<<" ";
cout<<endl;
}
}
int main()
{
while(cin >> n >> m)
{
if(!n && !m)break;
int u, v;
for(int i = ; i <= n; i++)Map[i].clear();
memset(Count, , sizeof(Count));
for(int i = ; i < m; i++)
{
cin >> u >> v;
Map[u].push_back(v);
Count[v]++;//存入度
}
topo();
}
return ;
}

时间复杂度:由于每个点入栈出栈一次,每条边扫描一次,时间复杂度为O(m + n)

 
 
 

AOV网络和Kahn算法拓扑排序的更多相关文章

  1. Java排序算法——拓扑排序

    package graph; import java.util.LinkedList; import java.util.Queue; import thinkinjava.net.mindview. ...

  2. 2017 ACM-ICPC(乌鲁木齐赛区)网络赛 H.Skiing 拓扑排序+最长路

    H.Skiing In this winter holiday, Bob has a plan for skiing at the mountain resort. This ski resort h ...

  3. 基于DFS的拓扑排序

    传送门:Kahn算法拓扑排序 摘录一段维基百科上的伪码: L ← Empty list that will contain the sorted nodes S ← Set of all nodes ...

  4. 算法-图(3)用顶点表示活动的网络(AOV网络)Activity On Vertex NetWork

    对于给定的AOV网络,必须先判断是否存在有向环. 检测有向环是对AOV网络构造它的拓扑有序序列,即将各个顶点排列成一个线性有序的序列,使得AOV网络中所有直接前驱和直接后继关系都能得到满足. 这种构造 ...

  5. 【数据结构与算法Python版学习笔记】图——拓扑排序 Topological Sort

    概念 很多问题都可转化为图, 利用图算法解决 例如早餐吃薄煎饼的过程 制作松饼的难点在于知道先做哪一步.从图7-18可知,可以首先加热平底锅或者混合原材料.我们借助拓扑排序这种图算法来确定制作松饼的步 ...

  6. 拓扑排序 (Topological Sorting)

    拓扑排序(Topological Sorting) 一.拓扑排序 含义 构造AOV网络全部顶点的拓扑有序序列的运算称为拓扑排序(Topological Sorting). 在图论中,拓扑排序(Topo ...

  7. python拓扑排序

    发现自己并没有真的理解拓扑排序和多重继承,再次学习了下 拓扑排序要满足如下两个条件 每个顶点出现且只出现一次. 若A在序列中排在B的前面,则在图中不存在从B到A的路径. 拓扑排序算法 任何无回路的顶点 ...

  8. nyoj349 poj1094 Sorting It All Out(拓扑排序)

    nyoj349   http://acm.nyist.net/JudgeOnline/problem.php?pid=349poj1094   http://poj.org/problem?id=10 ...

  9. POJ1094 拓扑排序

    问题:POJ1094   本题考查拓扑排序算法   拓扑排序:   1)找到入度为0的点,加入已排序列表末尾: 2)删除该点,更新入度数组.   循环1)2)直到 1. 所有点都被删除,则找到一个拓扑 ...

随机推荐

  1. MSIL实用指南-生成属性

    本篇讲解怎么生成属性,包括get和set方法. 第一步,生成一个字段生成字段用TypeBuilder.DefineField方法.实例代码: FieldBuilder customerNameBldr ...

  2. TortoiseGit- 创建本地新分支,提交推送到远程,本地新分支合并到工作分支,提交到远程工作分支等。

    整体思路: 创建本地新分支 (create branch)  -- 切换到本地新分支工作 (switch/checkout) --提交修改 (commit)  -- 推送到远程新分支 (push)  ...

  3. Python第二话 初识复杂数据类型(list、dictionary、tuple)

    上一篇我们简单认识了数据类型:数字number和字符串string,这篇我们就来隆重介绍一下重量级的数据类型:列表list.字典dictionary和元组tuple. 一.列表List: ①列表是什么 ...

  4. python 面向对象的程序设计

    一:什么是编程范式? 编程是程序员用特定的语法 + 数据结构 + 算法组成的代码来告诉计算机如何执行任务的过程. 如果把编程的过程比喻为练习武功,那么编程范式指的就是武林中的各种流派,而在编程的世界里 ...

  5. C语言程序设计(基础)- 第7周作业(新)

    要求一(25经验值) 完成PTA中题目集名为<usth-C语言基础-第七周作业>和<usth-C语言基础-12周PTA作业>中的所有题目. 注意1:<usth-C语言基础 ...

  6. alpha-咸鱼冲刺day8

    一,合照 emmmmm.自然还是没有的. 二,项目燃尽图 三,项目进展 正在进行页面整合.然后还有注册跟登陆的功能完善-- 四,问题困难 数据流程大概是搞定了.不过语法不是很熟悉,然后还有各种判定. ...

  7. 简易web服务器

    当通过Socket开发网络应用程序的时候,首先需要考虑所使用的网络类型,主要包括以下三个方面: 1)Socket类型,使用网络协议的类别,如IPv4的类型为PF_INET. 2)数据通信的类型,常见的 ...

  8. 《Language Implementation Patterns》之 增强解析模式

    上一章节讲述了基本的语言解析模式,LL(k)足以应付大多数的任务,但是对一些复杂的语言仍然显得不足,已付出更多的复杂度.和运行时效率为代价,我们可以得到能力更强的Parser. Pattern 5 : ...

  9. scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250

    scrapy爬虫框架教程(二)-- 爬取豆瓣电影TOP250 前言 经过上一篇教程我们已经大致了解了Scrapy的基本情况,并写了一个简单的小demo.这次我会以爬取豆瓣电影TOP250为例进一步为大 ...

  10. python 之反射

    通过字符串的形式导入模块 通过字符串的形式,去模块中寻找制定的函数,并执行getattr(模块名,函数名,默认值) 通过字符串的形式,去模块中设置东西setattr(模块名,函数名/变量名,lambd ...