图——活动网络

AOV网

  顶点表示活动的网络AOV,用顶点表示活动或任务,边表示活动或任务之间的优先关系的优先图G。

定义:从i到j存在一条路径,i为顶点j的前驱,<i,j>直接前驱。后继,直接后继

  优先关系是传递的,判断优先关系是否反自反较困难,如果优先关系不是反自反的,那么存在那就存在一个活动是其自身的前驱。

  判断AOV网络中不存在优先环路,可以证明优先关系是反自反的。

拓扑排序:所有顶点在一个先行序列中,对于图中的任意两个顶点i和j,i是j的前驱,则i在排序在j的前面。

topsort算法:

  1.列出没有前驱的所有顶点

  2.删除这些顶点及其出边

重复知道所有顶点被列出。

AOV网络
// AOV网,顶点活动网络,用于表示活动或者任务之间的优先关系。例如选课工程中,一些课程必须在其他课程修完,才能再修。
//定义 AOV网中,前驱,直接前驱,后继,直接后继
//AOV 网络中优先关系必须是传递和反自反的。
//AOV 网络中对图进行top排序,可以确定各顶点间的前驱和后继。也可以确定图有没有环

class AOV
{
public:
AOV():graph(NULL){}
void SetGraph(Graph_Adjacency * p){graph=p;}
void TopSort(); //AOV网络的拓扑排序

vector
<int> * Get_Result() { return &top_result;}

private:
Graph_Adjacency
*graph; //邻接表表示的图
vector<int> top_result;
};
拓扑排序
 1 /************************************************************************/
2 /* AOV 网络拓扑排序,去掉依次入度为0的节点和边,并入栈,
3 如果所有节点都访问过,则结束,或则存在又向环路 */
4 /************************************************************************/
5
6 void AOV::TopSort()
7 {
8 int n=graph->Get_Vertexs(); //节点数
9 head_node *inver=graph->Get_Inverse(); //邻接表
10 head_node *adj=graph->Get_Adjacency(); //逆邻接表
11 int *count= new int[n]; // 用于记录每个节点的入度
12 stack<int> stack;
13
14 //初始化
15 for (int i=0;i<n;i++)
16 {
17 count[i]=inver[i].count;
18 if (!count[i])
19 stack.push(i); //找出入度为空节点,入栈
20 }
21
22 for(i=0;i<n;i++)
23 {
24 //循环访问n个节点
25 if (stack.isEmpty())
26 {
27 cout<<"error: network has a cycle, topsort terminated"<<endl;
28 return;
29 }
30
31 int top=stack.Top();
32 stack.pop();
33
34 top_result.push_back(top);
35
36 //top入度为0,去掉top相连的边,则top相连的顶点vi 的入度-1
37 for (vertex_node*p=adj[top].link;p;p=p->link)
38 {
39 int temp=p->vertex;
40 count[temp]--;
41 //如果count[temp]
42 if (!count[temp])
43 {
44 stack.push(temp);
45 }
46 }
47 }
48
49 //输出
50 cout<<"the network top sort list is : ";
51 for (vector<int>::const_iterator iter=top_result.begin();iter!=top_result.end();++iter)
52 {
53 printf("v%d ",*iter);
54 }
55 cout<<endl;
56 }

top排序时间复杂度:

O(e+n)

 AOE网络(边活动网络)

图中优先边表示在一个工程中,表示所需要完成的任务或活动,而顶点表示事件,用来表示活动完成,当一个事件完成,就标志着所有该事件的所有活动都已完成。

AOE
 1 //边活动网络,图中又向边表示工程所需要完成的任务或活动,顶点表事件,
2 //当一个事件发生时表示该事件的所有活动都已完成。在工程中,活动是可以同时进行的。只有各自对应的事件发生时,活动才可以进行。
3 //AOE网络中评价工程执行情况,可确定工程执行的最少时间,和工程中活动关键性的评价
4 //关键路径:具有最长路径长度的路径
5 //关键活动,最迟开始时间和最早开始时间的差值,表明活动的关键程度,关键活动既是:early(i)=late(i)
6
7 class AOE
8 {
9 public:
10 AOE();
11 void SetGraph(Graph_Adjacency * p){graph=p;}
12 void critical_path(); //关键路径,返回关键路径长度
13 void critical_activity(); //关键活动
14 int Get_Path_Length(int v); //获取顶点v的路径长度
15
16 private:
17 Graph_Adjacency *graph;
18 int earliest[max_vertexs]; //记录事件最早开始时间
19 int latest[max_vertexs]; //记录事件最晚开始时间
20 int start,end; //AOE 网络中开始和结束顶点。
21 };

 在AOE网络中,有些活动可以并行进行,所以完成整个工程所需时间是从开始顶点到终止节点的最长路径长度。关键路径就是具有最长路径长度的路径。

在AOE网络中,关键路径可能不止一条。

事件vi,最早发生时间,是从v0到vi的最长路径长度,把活动ai的最早开始时间记为early(i)

活动ai最迟开始时间,late[i],在比增加工期前提下,活动ai最迟能够开始的时间。

关键活动:earl[i]==late[i]

计算AOE网络中,所有活动的最早eary[i],最晚late[i] 开始时间。就可以确定哪些活动是关键活动,去掉非关键活动,从开始到结束得到的路径就是关键路径。

AOE
  1 /************************************************************************/
2 /* AOE 网络 */
3 /************************************************************************/
4
5 AOE::AOE()
6 {
7 graph=NULL;
8 memset(earliest,0,sizeof(int)*max_vertexs);
9 memset(latest,0,sizeof(int)*max_vertexs);
10 start=0;
11 end=0;
12
13 }
14
15
16 //关键活动
17 void AOE::critical_activity()
18 {
19 /*
20 //首先确定每个节点事件的最早开始,最晚开始时间.
21 //可以按有向图AOV网路中,top排序序列依次确定顶点的最早开始时间。可以确定,earlist(j)=max(earist(i)+<i,j>持续时间),i是j的直接前驱
22 //这样通过top排序,可以确定earlist(i)在earlist[j]前先算出
23 */
24
25 //AOV 确定top排序
26 AOV aov;
27 aov.SetGraph(graph);
28 aov.TopSort();
29
30 head_node *adj=graph->Get_Adjacency();
31 head_node *inv=graph->Get_Inverse();
32 int n=graph->Get_Vertexs();
33
34 vertex_node *p=NULL;
35
36 //求earlist
37 vector<int> *result=aov.Get_Result();
38 for (vector<int>::const_iterator iter=result->begin();iter!=result->end();++iter)
39 {
40 int v=*iter;
41 for (p=adj[v].link;p;p=p->link)
42 {
43 int w=p->vertex;
44 if (earliest[v]+p->weight > earliest[w])
45 earliest[w]=earliest[v]+p->weight;
46 }
47
48 }
49 /*
50 //求latest
51 //latest 求法和earlist相同,不过是从top排序逆序列开始算最迟开始时间,依次算出其前驱的latest
52 //latest[i]=min(latest[j]-<i,j>),其中j是i直接后继。
53 */
54
55 int critical=earliest[n-1];
56 for(int i=0;i<n;i++)
57 {
58 latest[i]=critical;
59 }
60 for (vector<int>::reverse_iterator r_iter=result->rbegin();r_iter!=result->rend();++r_iter)
61 {
62 int v=*r_iter;
63 for(p=inv[v].link;p;p=p->link)
64 {
65 int w=p->vertex;
66 if (latest[v]-p->weight<latest[w])
67 latest[w]=latest[v]-p->weight;
68 }
69 }
70
71 //通过vi事件的earlist和latest,事件的最早最迟开始时间
72 //求活动的最早和最迟开始时间
73 //假设 k=<i,j> 表示一个活动,k最早开始时间eary(k)=earlist[i],最迟开始时间late[k]=latest[j]-<i,j>持续时间
74
75 vector<Edge> critical_set;
76 for (i=0;i<n;i++)
77 {
78 //遍历所有活动即边
79 int from=0,to=0;
80 for (p=adj[i].link;p;p=p->link)
81 {
82 from=i,to=p->vertex;
83 int activity_degree=activity_degree=latest[to]-p->weight-earliest[from]; //活动程度即活动的最迟开始时间-最早开始时间
84 if (activity_degree==0)
85 {
86 //关键活动
87 Edge cri(from,to,p->weight);
88 critical_set.push_back(cri);
89 }
90 }
91 }
92
93 //输出所有关键活动
94 cout<<"the critical activity:"<<endl;
95 for (vector<Edge>::iterator cri_iter=critical_set.begin();cri_iter!=critical_set.end();++cri_iter)
96 cri_iter->print();
97 cout<<endl;
98
99 }
100
101
102
103 //关键路径
104 void AOE::critical_path()
105 {
106 //有关键路径所组成的图G'
107 //在G'中找出从开始到结束节点的一条路径,则为关键路径
108 }

 

 

 

posted on 2011-09-17 20:08  youngkang  阅读(890)  评论(0)    收藏  举报