【问题描述】若在带权的有向图中,以顶点表示事件,以有向边表示活动,边上的权值表示活动的开销(如该活动持续的时间),则此带权的有向图称为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
#include<iostream>
#include<stack>
using namespace std;
#define MAXNUM 9999
typedef struct ArcNode
{
int adjvex;
int weight;
struct ArcNode *next;
}ArcNode;
typedef struct VexNode
{
int indegree;
ArcNode *firstarc;
}VexNode;
typedef struct
{
VexNode vex[MAXNUM];
int vexnum,arcnum;
}Graph;
void Create(Graph &g)
{
cin>>g.vexnum>>g.arcnum;
for(int i=0;i<g.vexnum;i++)
{
g.vex[i].firstarc=NULL;
g.vex[i].indegree=0;
}
ArcNode *p=NULL,*q=NULL;
for(int x=0;x<g.arcnum;x++)
{
int i,j,k;
cin>>i>>j>>k;
p=new ArcNode;
p->adjvex=j;
p->next=NULL;
p->weight=k;
q=g.vex[i].firstarc;
if(q==NULL)
{
g.vex[i].firstarc=p;
}
else
{
while(q->next!=NULL)
{
q=q->next;
}
q->next=p;
}
g.vex[j].indegree++;
}
}
int TopoSort(Graph g,int s1[MAXNUM],int ve[MAXNUM])
{
stack<int> S;
int Count,k,i,j,m=0;
ArcNode *p;
for(i=0;i<g.vexnum;i++)
{
if(g.vex[i].indegree==0) S.push(i);
}
for(i=0;i<g.vexnum;i++)//将每个点的最早发生时间初始化为0
{
ve[i]=0;
}
while(!S.empty())
{
j=S.top();
S.pop();
s1[m]=j; m++;
p=g.vex[j].firstarc;
while(p!=NULL)
{
k=p->adjvex;
g.vex[k].indegree--;
if(g.vex[k].indegree==0) S.push(k);
if(ve[j]+p->weight>ve[k]) ve[k]=ve[j]+p->weight;//更新结点的最早发生时间
p=p->next;
}
}
if(m!=g.vexnum) return 0;
else return 1;
}
int Path(Graph g,int T[MAXNUM])
{
int i,j,k,e,l,dut,vl[MAXNUM],ve[MAXNUM];
ArcNode *p;
if(!TopoSort(g,T,ve))//若存在环,则报错
{
cout<<"ERROR"<<endl;
return 0;
}
for(i=0;i<g.vexnum;i++)//初始化每个结点的最晚发生时间
{
vl[i]=ve[g.vexnum-1];
}
for(i=g.vexnum-1;i>=0;i--)//从后往前推每个结点的最晚发生时间
{
j=T[i]; p=g.vex[j].firstarc;
while(p!=NULL)
{
k=p->adjvex; dut=p->weight;
if(vl[k]-dut<vl[j]) {vl[j]=vl[k]-dut;}
p=p->next;
}
}
int a[MAXNUM],b[MAXNUM],Count=0,sum=0;
for(j=0;j<g.vexnum;j++)//算出每条边的最早和最晚发生时间
{
for(p=g.vex[j].firstarc;p;p=p->next)
{
k=p->adjvex; dut=p->weight;
e=ve[j]; l=vl[k]-dut;
if(e==l)
{
a[Count]=j; b[Count]=k; Count++;
}
}
}
cout<<ve[g.vexnum-1]<<endl;
for(i=0;i<Count;i++)
{
cout<<a[i]<<" "<<b[i]<<endl;
}
return 1;
}
int main()
{
Graph g;
int i,k,s1[MAXNUM],ve[MAXNUM];
Create(g); Path(g,s1);
return 0;
}
【问题描述】
在带权有向图G中,给定一个源点v,求从v到G中的其余各顶点的最短路径问题,叫做单源点的最短路径问题。
在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。
可将迪杰斯特拉算法描述如下:
在本题中,读入一个有向图的带权邻接矩阵(即数组表示),建立有向图并按照以上描述中的算法求出源点至每一个其它顶点的最短路径长度。
【输入形式】
输入的第一行包含2个正整数n和s,表示图中共有n个顶点,且源点为s。其中n不超过50,s小于n。
以后的n行中每行有n个用空格隔开的整数。对于第i行的第j个整数,如果大于0,则表示第i个顶点有指向第j个顶点的有向边,且权值为对应的整数值;如果这个整数为0,则表示没有i指向j的有向边。当i和j相等的时候,保证对应的整数为0。
【输出形式】
只有一行,共有n-1个整数,表示源点至其它每一个顶点的最短路径长度。如果不存在从源点至相应顶点的路径,输出-1。
请注意行尾输出换行。
【样例输入】
4 1
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0
【样例输出】
6 4 7
【样例说明】
在本题中,需要按照题目描述中的算法完成迪杰斯特拉算法,并在计算最短路径的过程中将每个顶点是否可达记录下来,直到求出每个可达顶点的最短路径之后,算法才能够结束。
迪杰斯特拉算法的特点是按照路径长度递增的顺序,依次添加下一条长度最短的边,从而不断构造出相应顶点的最短路径。
另外需要注意的是,在本题中为了更方便的表示顶点间的不可达状态,可以使用一个十分大的值作为标记。
#include<iostream>
using namespace std;
#define MAXNUM 100
#define MAX 999
typedef struct
{
int arcs[MAXNUM][MAXNUM];
int vexnum,arcnum;
}Graph;
int P[MAXNUM][MAXNUM];
int D[MAXNUM];
void Create(Graph &g,int m)
{
g.vexnum=m;
for(int i=0;i<g.vexnum;i++)
{
for(int j=0;j<g.vexnum;j++)
{
int n;
cin>>n;
if(n==0) g.arcs[i][j]=MAX;
else g.arcs[i][j]=n;
}
}
}
void ShortestPath_DIJ(Graph g,int v0)
{
int i=0,j,v,w,Min;
bool Final[MAXNUM];//为true表示已经求得v0到v的最短路径
for(v=0;v<g.vexnum;v++)
{
Final[v]=0;//初始化为false
D[v]=g.arcs[v0][v];//初始化最短路径为v0直接到v
for(w=0;w<g.vexnum;w++)
P[v][w]=0;//设空路径
if(D[v]<MAX)//将可以直接到达的点加入路径
{
P[v][v0]=1;
P[v][v]=1;
}
}
D[v0]=0; Final[v0]=1;//初始化,v0属于s集
for(i=1;i<g.vexnum;i++)
{
Min=MAX;
for(w=0;w<g.vexnum;w++)
{
if(!Final[w])//w点在v-s集
if(D[w]<Min)
{
v=w; Min=D[w];
}
}
Final[v]=1;//离v0最近的v加入s集
for(w=0;w<g.vexnum;w++)
if(!Final[w]&&(Min+g.arcs[v][w]<D[w]))
{
D[w]=Min+g.arcs[v][w];
for(j=0;j<g.vexnum;j++) P[w][j]=P[v][j];
P[w][w]=1;
}
}
}
int main()
{
int m,n;
cin>>m>>n;
Graph g;
Create(g,m);
ShortestPath_DIJ(g,n);
for(int i=0;i<m;i++)
{
if(D[i]==MAX) D[i]=-1;
}
for(int i=0;i<m;i++)
{
if(i!=n)
cout<<D[i]<<" ";
}
return 0;
}