拓扑排序的实现_TopoSort
拓扑排序是求一个AOV网(顶点代表活动, 各条边表示活动之间的率先关系的有向图)中各活动的一个拓扑序列的运算, 可用于測试AOV
网络的可行性.
整个算法包含三步:
1.计算每一个顶点的入度, 存入InDegree数组中.
2.检查InDegree数组中顶点的入度, 将入度为零的顶点进栈.
3.不断从栈中弹出入度为0的顶点并输出, 并将该顶点为尾的全部邻接点的入度减1, 若此时某个邻接点的入度为0, 便领其进栈. 反复步骤
3, 直到栈为空时为止. 此时, 或者所有顶点都已列出, 或者因图中包括有向回路, 顶点未能所有列出.
实现代码:
#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "queue"
#include "stack"
#include "cmath"
#include "utility"
#include "map"
#include "set"
#include "vector"
#include "list"
#include "string"
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
enum ResultCode { Underflow, Overflow, Success, Duplicate, NotPresent, Failure, HasCycle };
template <class T>
struct ENode
{
ENode() { nxtArc = NULL; }
ENode(int vertex, T weight, ENode *nxt) {
adjVex = vertex;
w = weight;
nxtArc = nxt;
}
int adjVex;
T w;
ENode *nxtArc;
/* data */
};
template <class T>
class Graph
{
public:
virtual ~Graph() {}
virtual ResultCode Insert(int u, int v, T &w) = 0;
virtual ResultCode Remove(int u, int v) = 0;
virtual bool Exist(int u, int v) const = 0;
/* data */
};
template <class T>
class LGraph: public Graph<T>
{
public:
LGraph(int mSize);
~LGraph();
ResultCode Insert(int u, int v, T &w);
ResultCode Remove(int u, int v);
bool Exist(int u, int v) const;
int Vertices() const { return n; }
void Output();
protected:
ENode<T> **a;
int n, e;
/* data */
};
template <class T>
void LGraph<T>::Output()
{
ENode<T> *q;
for(int i = 0; i < n; ++i) {
q = a[i];
while(q) {
cout << '(' << i << ' ' << q -> adjVex << ' ' << q -> w << ')';
q = q -> nxtArc;
}
cout << endl;
}
cout << endl << endl;
}
template <class T>
LGraph<T>::LGraph(int mSize)
{
n = mSize;
e = 0;
a = new ENode<T>*[n];
for(int i = 0; i < n; ++i)
a[i] = NULL;
}
template <class T>
LGraph<T>::~LGraph()
{
ENode<T> *p, *q;
for(int i = 0; i < n; ++i) {
p = a[i];
q = p;
while(p) {
p = p -> nxtArc;
delete q;
q = p;
}
}
delete []a;
}
template <class T>
bool LGraph<T>::Exist(int u, int v) const
{
if(u < 0 || v < 0 || u > n - 1 || v > n - 1 || u == v) return false;
ENode<T> *p = a[u];
while(p && p -> adjVex != v) p = p -> nxtArc;
if(!p) return false;
return true;
}
template <class T>
ResultCode LGraph<T>::Insert(int u, int v, T &w)
{
if(u < 0 || v < 0 || u > n - 1 || v > n - 1 || u == v) return Failure;
if(Exist(u, v)) return Duplicate;
ENode<T> *p = new ENode<T>(v, w, a[u]);
a[u] = p;
e++;
return Success;
}
template <class T>
ResultCode LGraph<T>::Remove(int u, int v)
{
if(u < 0 || v < 0 || u > n - 1 || v > n - 1 || u == v) return Failure;
ENode<T> *p = a[u], *q = NULL;
while(p && p -> adjVex != v) {
q = p;
p = p -> nxtArc;
}
if(!p) return NotPresent;
if(q) q -> nxtArc = p -> nxtArc;
else a[u] = p -> nxtArc;
delete p;
e--;
return Success;
}
template <class T>
class ExtLgraph: public LGraph<T>
{
public:
ExtLgraph(int mSize): LGraph<T>(mSize) {}
void TopoSort(int *order);
private:
void CallInDegree(int *InDegree);
/* data */
};
template <class T>
void ExtLgraph<T>::TopoSort(int *order)
{
int *InDegree = new int[LGraph<T>::n];
int top = -1; // 置栈顶指针为-1, 代表空栈
ENode<T> *p;
CallInDegree(InDegree); // 计算每一个顶点的入度
for(int i = 0; i < LGraph<T>::n; ++i)
if(!InDegree[i]) { // 图中入度为零的顶点进栈
InDegree[i] = top;
top = i;
}
for(int i = 0; i < LGraph<T>::n; ++i) { // 生成拓扑排序
if(top == -1) throw HasCycle; // 若堆栈为空, 说明图中存在有向环
else {
int j = top;
top = InDegree[top]; // 入度为0的顶点出栈
order[i] = j;
cout << j << ' ';
for(p = LGraph<T>::a[j]; p; p = p -> nxtArc) { // 检查以顶点j为尾的全部邻接点
int k = p -> adjVex; // 将j的出邻接点入度减1
InDegree[k]--;
if(!InDegree[k]) { // 顶点k入度为0时进栈
InDegree[k] = top;
top = k;
}
}
}
}
}
template <class T>
void ExtLgraph<T>::CallInDegree(int *InDegree)
{
for(int i = 0; i < LGraph<T>::n; ++i)
InDegree[i] = 0; // 初始化InDegree数组
for(int i = 0; i < LGraph<T>::n; ++i)
for(ENode<T> *p = LGraph<T>::a[i]; p; p = p -> nxtArc) // 检查以顶点i为尾的全部邻接点
InDegree[p -> adjVex]++; // 将顶点i的邻接点p -> adjVex的入度加1
}
int main(int argc, char const *argv[])
{
ExtLgraph<int> lg(9);
int w = 10; lg.Insert(0, 2, w); lg.Insert(0, 7, w);
lg.Insert(2, 3, w); lg.Insert(3, 5, w);
lg.Insert(3, 6, w); lg.Insert(4, 5, w);
lg.Insert(7, 8, w); lg.Insert(8, 6, w);
int *order = new int[9];
lg.TopoSort(order);
cout << endl;
delete []order;
return 0;
}
拓扑排序的实现_TopoSort的更多相关文章
- 算法与数据结构(七) AOV网的拓扑排序
今天博客的内容依然与图有关,今天博客的主题是关于拓扑排序的.拓扑排序是基于AOV网的,关于AOV网的概念,我想引用下方这句话来介绍: AOV网:在现代化管理中,人们常用有向图来描述和分析一项工程的计划 ...
- 有向无环图的应用—AOV网 和 拓扑排序
有向无环图:无环的有向图,简称 DAG (Directed Acycline Graph) 图. 一个有向图的生成树是一个有向树,一个非连通有向图的若干强连通分量生成若干有向树,这些有向数形成生成森林 ...
- 【BZOJ-2938】病毒 Trie图 + 拓扑排序
2938: [Poi2000]病毒 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 609 Solved: 318[Submit][Status][Di ...
- BZOJ1565 [NOI2009]植物大战僵尸(拓扑排序 + 最大权闭合子图)
题目 Source http://www.lydsy.com/JudgeOnline/problem.php?id=1565 Description Input Output 仅包含一个整数,表示可以 ...
- 图——拓扑排序(uva10305)
John has n tasks to do. Unfortunately, the tasks are not independent and the execution of one task i ...
- Java排序算法——拓扑排序
package graph; import java.util.LinkedList; import java.util.Queue; import thinkinjava.net.mindview. ...
- poj 3687(拓扑排序)
http://poj.org/problem?id=3687 题意:有一些球他们都有各自的重量,而且每个球的重量都不相同,现在,要给这些球贴标签.如果这些球没有限定条件说是哪个比哪个轻的话,那么默认的 ...
- 拓扑排序 - 并查集 - Rank of Tetris
Description 自从Lele开发了Rating系统,他的Tetris事业更是如虎添翼,不久他遍把这个游戏推向了全球. 为了更好的符合那些爱好者的喜好,Lele又想了一个新点子:他将制作一个全球 ...
- *HDU1285 拓扑排序
确定比赛名次 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Subm ...
随机推荐
- 2t3ik、ddgs与Linux异常文件下载处理
异常1: 这样的邮件发生了两周了,烦得很.进入服务器,用top看来下进程. 解决办法 首先 kill 相关PID 进入/tmp/ 删除相关文件 rm -rf 2t3ik相关文件 不给相关文件修改权 ...
- MYSQL注入天书之基础知识
第一部分/page-1 Basic Challenges Background-1 基础知识 此处介绍一些mysql注入的一些基础知识. (1)注入的分类---仁者见仁,智者见智. 下面这个是阿德玛表 ...
- 第4天:Ansible模块
Ansible对远程服务器的实际操作实际是通过模块完成的,其工作原理如下: 1)将模块拷贝到远程服务器 2)执行模块定义的操做,完成对服务器的修改 3)在远程服务器中删除模块 需要说明的是,Ansib ...
- 【BZOJ 1119】 1119: [POI2009]SLO (置换)
1119: [POI2009]SLO Description 对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次 ...
- [BZOJ1444]有趣的游戏(AC自动机+矩阵乘法)
n个等长字符串,机器会随机输出一个字符串(每个字母出现的概率为p[i]),问每个字符串第一个出现的概率是多少. 显然建出AC自动机,套路地f[i][j]表示i时刻位于节点j的概率. 构建转移矩阵,当i ...
- JZYZOJ1372 [noi2002]荒岛野人 扩展欧几里得
http://172.20.6.3/Problem_Show.asp?id=1372 想法其实很好想,但是我扩展欧几里得还是用得不熟练,几乎是硬套模板,大概因为今天一个下午状态都不大好.扩展欧几里得算 ...
- BZOJ 3399 [Usaco2009 Mar]Sand Castle城堡(贪心)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3399 [题目大意] 将一个集合调整成另一个集合中的数,把一个数+1需要消耗x,-1需要 ...
- 【二分】【三分】【计算几何】XIII Open Championship of Y.Kupala Grodno SU Grodno, Saturday, April 29, 2017 Problem L. Lines and Polygon
题意:给你一个凸多边形,和多次询问,每次询问给你一条直线,问你这条直线与凸包上的顶点的最近距离是多少. 记当前询问的直线的斜率为K, 先找到与这条直线距离最远的两个点: 就把凸包所有的边当做有向直线进 ...
- 【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles
给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子. 把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队).然后从大到小排序.然后用并查集将相邻(四联 ...
- java笔记之方法
一.那么什么是方法呢? 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块 方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 二.方法的优点 ...