文章出自:
拓撲排序和關鍵路徑
拓撲排序
拓撲排序最大的用途就是判斷乙個有向圖是否有環,當然判斷還有一種方法就是floyd演算法。如果用鄰接表的話拓撲排序的時間複雜度是o(n*e),鄰接矩陣是o(n^2),n表示頂點數,e表示邊數,floyd時間複雜度是o(n^3)。
拓撲排序方法可分為無前趨的頂點優先的拓撲排序方法和無後繼的頂點優先的拓撲排序方法。
基本拓撲排序演算法步驟
1.在有向圖中任選乙個沒有前驅的頂點輸出
2.從圖中刪除該頂點和所有以它為起點的邊
3.重複1和2,直到全部頂點都以輸出
拓撲排序的實現(無前趨的頂點優先的拓撲排序方法)
鄰接表實現(使用stack儲存)
c**
/**********************************
title: 拓撲排序(鄰接表實現)
author: jay chang
date: 2009/07/16
**********************************/
#include
#define maxsize 99
#define true 1
#define false 0
using
namespace std;
typedef
char vertexdata;
typedef
int adjtype;
typedef
struct stack //定義棧
stack;
typedef
struct arcnode //定義弧結點
arcnode;
typedef
struct vertexnode //定義頂點
vertexnode;
typedef
struct adjmatrix //定義圖
adjmatrix;
//全域性變數
int indegree[maxsize+1]=;
int locategraph(adjmatrix *g, vertexdata vertexdata)
return false;
} void creategraph(adjmatrix *g)
for(icount=1;icount<=g->arcnum;icount++)
} //判棧空
int isempty(stack *stack)
//初始化棧
void initstack(stack *stack)
//出棧
void pop(stack *stack,int *iindex)
//進棧
void push(stack *stack,int value)
//拓撲排序
int topological(adjmatrix *g)
} cout<
//輸出頂點後,將與該頂點相連的頂點的邊刪除,將與相連頂點的入度減1,如減後為0,入棧,棧空結束
while(!isempty(stack))
}//end while
if(countvernum)
cout
int main()
**基於dfs實現(無後繼的頂點優先的拓撲排序方法)
cpp**
#include
using
namespace std;
int timef = 0;
int n ;
int a[1000][1000];// 圖的鄰接矩陣
int f[1000]; //完成時間
int vis[1000]; //1代表 被發現 2代表 已完成
void dfs(int u)
void dfs_main() //o(v+e)
} void topological_sort() //o(v+e)
int main()
**關鍵路徑
相關量介紹,設源點v0,匯點vn-1:
ve(i)表示事件vi最早發生的時間,vl(i)表示事件vi最晚發生的時間。
ve(0)=0,按拓撲排序計算ve(i)的值,ve(j)=max。
vl(n-1)=ve(n-1),vl(i)按逆拓撲排序進行計算,vl(i)=min。
活動最早開始時間ee(i)=ve(i);活動最晚開始時間el(i,j)=vl(j)-w(i,j),如果el(i,j)=ee(i,j),則活動是關鍵活動。
關鍵路徑演算法的流程
1.以拓撲排序的次序按ve(j)=max計算各個頂點(事件)最早發生的時刻
2.以逆拓撲排序的次序按vl(j)=min計算各個頂點(事件)最晚發生的時刻
3.計算每個活動發生的最早時間ee(i,j)和最晚時間el(i,j),如果滿足ee(i,j)=el(i,j)則是關鍵路徑並輸出。
關鍵路徑演算法實現
cpp**
#include
using
namespace std;
#define max 10000000
#define max_vertex_num 20
int ve[max_vertex_num];
/*順序棧的定義*/
#define stack_size 100
typedef
struct sqstack
sqstack;
/*順序棧的初始化*/
void initstack_sq(sqstack &s)
/*入棧*/
void push(sqstack &s,int x)
/*出棧*/
int pop(sqstack &s)
typedef
struct edgenode
edgenode;
typedef
struct vexnode
vexnode;
typedef
struct
lgraph;
/*構造有向圖的鄰接表*/
void createdg_al(lgraph &g,int n,int e)
for(k=0;k
}
//拓撲排序並求各頂點事件的最早發生時間及拓撲逆序列
void toposort(lgraph &g,sqstack &t)
}
for(i=0;iif(g.vexs[i].indegree==0)
push(s,i);//將度為0的頂點入棧,這裡進棧的是入度為0的頂點在陣列中的位置
for(i=0;ive[i]=0;//初始化頂點事件的最早發生時間為0
while(s.top!=-1)
}
cout
//求關鍵路徑和關鍵活動
void criticalpath(lgraph &g)
}
for(i=0;i
}
}
}
void main()
**
小結 這篇文章講了有關有向無環圖的兩個應用,最要將能熟悉拓撲排序和關鍵路徑的演算法的原理就能加以應用
拓撲排序和關鍵路徑
拓撲排序 乙個無環的有向圖稱為無環圖 directed acyclic graph 簡稱dag圖。所有的工程或者某種流程都可以分為若干個小的工程或者階段,稱這些小的工程或階段為 活動 這些子程式之間存在一定的約束,其中某種子工程的開始必須在另一些子工程完成之後。因此dag圖表示乙個工程,其中有向邊表...
拓撲排序和關鍵路徑
拓撲排序 乙個無環的有向圖稱為無環圖 directed acyclic graph 簡稱dag圖。所有的工程或者某種流程都可以分為若干個小的工程或者階段,稱這些小的工程或階段為 活動 這些子程式之間存在一定的約束,其中某種子工程的開始必須在另一些子工程完成之後。因此dag圖表示乙個工程,其中有向邊表...
拓撲排序和關鍵路徑
include include include include includeusing namespace std struct node const int maxv 1010 vectorg maxv 鄰接表 int n,m,indegree maxv 頂點數 邊數 入度 ve是事件最早到達時...