AOE网问题和解决
课程设计有这个题目所有将解决AOE网(附代码)做什么都得先构想好,理解到理解好,静下心来思考后再去用代码实现构想。
AOE的概念:Activity On Edge.也就是说我们用边代表活动。顶点表示事件。弧头,弧尾都是事件,弧上的权值表示活动的持续时间。因此这样的有向图也被称作活动网。
关键路径
- 具有最大路径长度的路径称为关键路径。
- 关键路径上的活动称为关键活动。
因此,关键路径的长度是整个工程所需要的最短工期。
设计算法前先分事件和活动借图理解
选取数据结构为有向图
存储事件为节点 节点值V1~V9 对应 节点值为A~I
事件最早开始时间
事件的最早发生时间e[Vk], v是vertex,表示顶点,e是early,表示早。e[Vk]的计算从左往右按照箭头的指示进行。其中初态e[V1] = 0,即起点最早发生时间是0时刻。
e[V1] = 0;
e[V2] = 6;
e[V3] = 4;
e[V4] = 5;
e[V5] = max(e[V2]+1,e[V3]+1) = 7;
即上一事件的所的最早开始时间和上一事件和要求事件中的活动a?的所需时间即弧的权值之和取最大值。 代码中用数组的索引找到上一事件所对应的节点
e[V6] = 7;
e[V7] = 16;
e[V8] = max(e[V5]+7,e[V6]+4) = 14;
e[V9] = max(e[V7]+2,e[V8]+4) = 18;
根据下面公式可得如上答案
e[V0] = 0; 初始事件时间为0;
e[Vk] = max(e[Vj]] +len(Vj,Vk) );
活动最早开始时间
e[1] = e[V1] = 0;
e[2] = e[V1] = 0;
e[3] = e[V1] = 0;
e[4] = e[V2] = 6;
e[5] = e[V3] = 4;
e[6] = e[V4] = 5;
e[7] = e[V5] = 7;
e[8] = e[V5] = 7;
e[9] = e[V6] = 7;
e[10] = e[V7] =16;
e[11] = e[V8] = 14;
不难 发现活动最早开始时间为活动对应前一个事件 (即弧头事件)的最早开始时间
e[ i ] = e[Vj];
事件最晚允许开始时间
l[V9] = e[V9] = 18;
l[V8] = l[V9]-4=14;
l[V7] = l[V9]-2 = 16;
l[V6] = l[V8]-4=10;
l[V5] = min(l[V7]-9,l[V8]-7) = 7;
l[V4] = vl[V6]-2=8;
l[V3] = 6;
l[V2] = 6;
l[V1] = min(l[V2]-6,l[V3]-4,l[V4]-5) = 0;
最后一个事件最晚允许开始时间是最后一个事件的开始时间
最后一个事件最晚允许开始时间
l[Vn] = e[Vn];
l[Vn] = min(l[Vk] - len(Vj,Vk)); k当前事件的下一事件
活动最晚允许开始时间
l[1] = l[V2] - 6 = 0;
l[2] = l[V3] - 4 = 2;
l[3] = l[V4] - 5 = 3;
l[4] = l[V5] - 1 = 6;
l[5] = l[V5] - 1 = 6;
l[6] = l[V6] - 2 = 8;
l[7] = l[V7] - 9 = 7;
l[8] = l[V8] - 7 = 7;
l[9] = l[V8] - 4 = 10;
l[10] = l[V9] - 2 = 16;
l[11] = l[V9] - 4 = 14;
计算结果为该活动所对应的事件的最晚允许开始时间减去该活动所对应的时间
l[ i ] = l[Vj] - len(Vj,Vk); j为当前活动所对应的弧头事件
最后附上代码
图用的之前写的,链接如下
图的存储 http://blog.csdn.net/lin1094201572/article/details/78826295
没有使用容器代码可输出结果最后完善
#include<iostream>
#include<String.h>
using namespace std;
class Node {
public:
char data;
bool isvisited;
public :
Node(char d = 0) {
data = d;
isvisited = false;
}
};
class MGraph {
private:
Node *m_NodeArray; //图的空间
int *m_Matric; //邻接矩阵空间
int m_nodecount; //结点个数
int m_capacity; //结点容量
public:
MGraph(int capacity) { //图的初始化
m_capacity = capacity; //图的节点最大个数
m_NodeArray = new Node[m_capacity+1000];
m_Matric = new int[m_capacity*m_capacity+1000];
m_nodecount = 0;
memset(m_Matric,0,m_capacity*m_capacity*sizeof(int));
}
~MGraph() {
delete []m_NodeArray;
delete []m_Matric;
}
//返回图节点个数
int getcount() {
return m_nodecount;
}
void AddMGraph(Node *node) { //添加结点
m_NodeArray[m_nodecount].data = node->data;
m_nodecount++;
}
//row代表上一节点index col表示下一节点index
bool setValueDirectedMatric(int row,int col,int val=1) { //插入邻接矩阵有向图图的权值默认为1
m_Matric[row*m_capacity + col] = val;
return true;
}
void getAll() {
int e[m_nodecount ];
//0 为 A 下标 aoe网开始
e[0] = 0;
/* printNodeData(0);
cout<<"--早开始时间:"<<e[0]<<endl;
*/
for(int i = 1 ; i < getcount(); i++) {
int index[2];//保存上一节点的在节点数组中的索引 限制两个
//找到该节点的前一个节点的索引
index[0] = 0; //附值
index[1] = 0; //索引n-1
int k = 0;
for( int row = 0; row < m_capacity; row++) {
//判断
if( getMatricvalue(row,i) > 0) {
index[k] = row;
k++;
} else {}
}
//循环输出索引
/*for( int j = 0 ; j < 2; j++){
cout<<index[j];
}*/
int max ; //最早开始时间 上一节点的最早开始时间 和两节点的权值 取和最大
if(index[0] >= 0 ) {
//cout<<index[0];
if(index[1] >= 0) {
// cout<<index[1]<<endl; //若index[1] 未初始化无值时报错停止运行
if((e[index[1]] + getMatricvalue(index[1],i))>(e[index[0]] + getMatricvalue(index[0],i))) {
max = (e[index[1]] + getMatricvalue(index[1],i));
} else {
max = (e[index[0]] + getMatricvalue(index[0],i));
}
} else {
max = (e[index[0]] + getMatricvalue(index[0],i));
}
}
e[i] = max;
/* printNodeData(i); //打印当前索引的节点data
cout<<"--早开始时间:"<<e[i]<<endl;*/
}
int l[m_nodecount - 1];
//最后一个事件的最晚开始时间 为该事件的最早开始时间
l[m_nodecount - 1] = e[m_nodecount - 1];
/*printNodeData(m_nodecount - 1);
cout<<"--最晚允许开始时间:"<<l[m_nodecount - 1]<<endl;*/
//循环为l[0] - l[m_nodecount - 2] 赋值
for( int i = getcount() - 2; i >= 0 ; i--) {
//存储下一节点索引index[] 限制两个。。。可完善
int index[3] = {0,0,0};
//index[0] = 0;
//index[1] = 0;
//index[2] = 0;
int k = 0;
//循环找到 i 索引当前的 下一节点索引
for ( int col = 0; col < m_capacity; col++) {
if( getMatricvalue(i,col) > 0) {
index[k] = col;
k++;
} else{}
}
// vl[n]=ve[n],n是最后一个事件的编号 vl[j]=min(vl[k] - len<vj,vk>)
//得到下一节点索引后取那个索引对应的l[index[]]-getMatricvalue(i,index[]) 最小
int min;
// >= 表示索引为0 时 下一个索引不可为0开始事件
if(index[0] > 0) {
//cout<< index[0];
if(index[1] > 0) {
//cout<<index[1];
if((l[index[0]]-getMatricvalue(i,index[0])) < (l[index[1]]-getMatricvalue(i,index[1]))) {
min = l[index[0]]-getMatricvalue(i,index[0]);
} else {
min = l[index[1]]-getMatricvalue(i,index[1]);
}
} else {
min = l[index[0]]-getMatricvalue(i,index[0]);
}
if(index[2] > 0){
//cout<<index[2];
if(min >(l[index[2]]-getMatricvalue(i,index[2])) ){
min = l[index[2]]-getMatricvalue(i,index[2]);
}
}
}
l[i] = min;
/* printNodeData(i);//打印当前索引的节点data
cout<<"--最晚允许开始时间:"<<l[i]<<endl;*/
}
//这个静态数组得到是所有活动的弧头事件的索引并将索引所对应的eary发生事件赋值 覆盖掉所存储的索引;
int eIndex[getValCount()];
int beginEaryIndex= 0;
//这个for循环得到的是所有活动的弧头事件的索引并 弧头 --------> 弧尾
for(int row = 0; row < m_capacity; row++){
for(int col = 0; col < m_capacity; col++){
if(getMatricvalue(row,col) > 0){
eIndex[beginEaryIndex++] = e[row];
}else{
continue;
}
}
}
int lIndex[getValCount()];
int lBeginIndex = 0;
for(int row = 0; row < m_capacity; row ++){
for(int col = 0; col < m_capacity; col++){
if(getMatricvalue(row,col) > 0){
lIndex[lBeginIndex++] = l[col] - getMatricvalue(row,col);
}else{
continue;
}
}
}
for( int j = 0; j < getValCount(); j ++){
cout<<"---活动a"<<j+1<<"--> ";
cout<<" --最早开始时间:"<<eIndex[j];
cout<<" --最晚允许开始时间:"<<lIndex[j]<<endl;
cout<<"------------------------------------------------------------------------"<<endl;
}
for(int j = 0 ; j < m_nodecount; j++) {
cout<<"---事件"<<m_NodeArray[j].data<<"--> ";
cout<<" --最早开始时间:"<<e[j];
cout<<" --最晚允许开始时间:"<<l[j]<<endl;
cout<<"------------------------------------------------------------------------"<<endl;
}
}
void printNodeData(int index) {
cout<<"---"<<m_NodeArray[index].data<<"--> ";
}
void printMatric() { //输出邻接矩阵
for(int i = 0 ; i<m_capacity ; i++) {
for(int j = 0 ; j<m_capacity ; j++) {
cout<<" "<<m_Matric[i*m_capacity + j];
}
cout<<endl;
}
}
int getMatricvalue(int row,int col) { //得到弧的权值
int val = m_Matric[row*m_capacity + col ];
return val;
}
int getValCount(){ //得到所有活动个数
int k = 0;
for(int i = 0 ; i < m_capacity*m_capacity; i++){
if( m_Matric[i] > 0){
k++;
}else{
continue;
}
}
return k;
}
};
int main() {
MGraph *m = new MGraph(9);
Node *node1 = new Node('A');
Node *node2 = new Node('B');
Node *node3 = new Node('C');
Node *node4 = new Node('D');
Node *node5 = new Node('E');
Node *node6 = new Node('F');
Node *node7 = new Node('G');
Node *node8 = new Node('H');
Node *node9 = new Node('I');
//添加图的结点
m->AddMGraph(node1);
m->AddMGraph(node2);
m->AddMGraph(node3);
m->AddMGraph(node4);
m->AddMGraph(node5);
m->AddMGraph(node6);
m->AddMGraph(node7);
m->AddMGraph(node8);
m->AddMGraph(node9);
m->setValueDirectedMatric(0,1,6);
m->setValueDirectedMatric(0,2,4);
m->setValueDirectedMatric(1,4,1);
m->setValueDirectedMatric(2,4,1);
m->setValueDirectedMatric(0,3,5);
m->setValueDirectedMatric(3,5,2);
m->setValueDirectedMatric(4,6,9);
m->setValueDirectedMatric(4,7,7);
m->setValueDirectedMatric(5,7,4);
m->setValueDirectedMatric(6,8,2);
m->setValueDirectedMatric(7,8,4);
cout<<"图的邻接矩阵"<<endl<<endl;
m->printMatric();
m->getAll();
return 0;
}