快一个月没更了,我好懒!!!
简要介绍
AOE网
若在带权的有向图中,以顶点表示事件,以有向边表示活动,边上的权值表示活动的开销(如该活动持续的时间),则此带权的有向图称为AOE网。
关键路径
如果用AOE网来表示一项工程,那么,仅仅考虑各个子工程之间的优先关系还不够,更多的是关心整个工程完成的最短时间是多少;哪些活动的延期将会影响整个工程的进度,而加速这些活动是否会提高整个工程的效率。这些活动(边)就叫关键路径。
题目介绍
输入形式:第一行输入两个数字,分别表示顶点数和边数;从第二行开始,输入边的信息,格式为(i,j, weight)
输出形式:关键路径的总时间(最大路径长度),代表关键活动的边,格式为(顶点1,顶点2),按大小顺序排列
【样例输入】
6 8
0 1 3
0 2 2
1 3 2
1 4 3
2 3 4
2 5 3
3 5 2
4 5 1
【样例输出】
8
0 2
2 3
3 5
算法思想
要求解关键路径我们得先了解四个重要概念:
事件最早发生时间(ETV)
顾名思义,事件最早发生时间就是顶点的最早发生时间,对0而言,其ETV自然是0,对1而言它的ETV就是其前驱事件的最早发生时间加上其活动的持续时间(a1),对3而言,其前驱事件有多个,就取最晚发生的那一个(ETV2+a5),其它的依次类推就好了
事件最晚发生事件(LTV)
就是最迟该事件需要开始的时间,不然就会延误时间。所以不难想到,LTV5=ETV5,对每个节点,其LTV就是其后继事件的最晚发生时间减去其活动持续时间,和ETV类似就不多赘述。
活动的最早开工时间(ETE)
显然,活动的最早开工时间就是活动发生前的事件的最早开始时间
活动的最晚开工时间(LTE)
活动的最晚开工时间,就是最迟该活动需要开始的时间,不然就会延误时间。如LTE3=LTV-a7。
知道ETV和LTV就可以求ETE和LTE,再次强调关键路径是活动的集合,所以得求ETE和LTE,
ETV和LTE相等的活动就是关键活动。
代码实现
#include <iostream>
#define maxsize 100
#include <stack>
using namespace std;
int like[maxsize]={0};
int flag=0;
int i,number=0,k,f=0;
int E[maxsize]={0},L[maxsize];
int pathe[maxsize][maxsize]={0};
int pathl[maxsize][maxsize]={0};
int keypoint[maxsize]={0};
stack <int>pathlike1;
stack <int>pathlike2;
stack <int>s;
struct ArcNode
{
int adjvex,weight;
ArcNode *nextarc=NULL;
};
struct VertexNode
{
int date,in,out,flag2;
ArcNode *firstarc;
};
struct AdjList
{
VertexNode vertex[maxsize];
int vexnum,arcnum;
};
void CreatGraph(AdjList *a)
{
int x,y,z;
for(int i=0;i<a->vexnum;i++)
{
a->vertex[i].date=i;
a->vertex[i].in=0;
a->vertex[i].out=0;
a->vertex[i].firstarc=NULL;
a->vertex[i].flag2=0;
}
for(int j=0;j<a->arcnum;j++)
{
cin>>x>>y>>z;
pathe[x][y]=z;
pathl[y][x]=z;
int flag1=0;
ArcNode *p=new ArcNode;
ArcNode *q=a->vertex[x].firstarc;
if(q)
{
flag1=1;
while(q->nextarc)
q=q->nextarc;
}
if(flag1)
q->nextarc=p;
else
a->vertex[x].firstarc=p;
p->adjvex=y;
p->weight=z;
a->vertex[x].out++;
a->vertex[y].in++;
}
for(i=0;i<a->vexnum;i++)
if(!a->vertex[i].in)
s.push(i),a->vertex[i].flag2=1;
}
void likeya (AdjList *a)
{
ArcNode *p;
while(!s.empty())
{
i=s.top();
s.pop();
like[flag++]=i;
number++;
p=a->vertex[i].firstarc;
while(p)
{
k=p->adjvex;
a->vertex[k].in--;
p=p->nextarc;
}
}
for(i=0;i<a->vexnum;i++)
if(a->vertex[i].in==0&&a->vertex[i].flag2==0)
s.push(i),a->vertex[i].flag2=1;
if(!s.empty())
likeya(a);
}
int topulike(AdjList *a)
{
likeya(a);
if(number<a->vexnum)
return 0;
else
return 1;
}
void gete()
{
E[0]=0;
for(i=1;i<flag;i++)
for(int j=0;j<flag;j++)
{
if(pathe[j][i]&&pathe[j][i]+E[j]>E[i])
E[i]=E[j]+pathe[j][i];
}
/* for(int j=0;j<flag;j++)
cout<<E[j]<<" ";
cout<<endl;*/
}
void getl()
{
for(int j=0;j<flag;j++)
L[j]=8888888;
L[flag-1]=E[flag-1];
for(i=flag-1;i>=1;i--)
for(int j=flag-2;j>=0;j--)
{
if(pathl[i][j]&&L[i]-pathl[i][j]<L[j])
L[j]=L[i]-pathl[i][j];
}
/*for(int j=0;j<flag;j++)
cout<<L[j]<<" ";
cout<<endl;*/
}
void likeend(AdjList *a)
{
int g,ete,lte;
ArcNode *e;
cout<<E[flag-1]<<endl;
for(int j=0;j<a->vexnum;j++)
{
for(e=a->vertex[j].firstarc;e;e=e->nextarc)
{
g=e->adjvex;
ete=E[j];
lte=L[g]-e->weight;
if(ete==lte)
cout<<a->vertex[j].date<<" "<<a->vertex[g].date<<endl;
}
}
}
int main()
{
AdjList a;
cin>>a.vexnum>>a.arcnum;
CreatGraph(&a);
if(topulike(&a))
gete();
getl();
likeend(&a);
return 0;
}