AOE网上的关键路径
Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
一个无环的有向图称为无环图(Directed Acyclic Graph),简称DAG图。
AOE(Activity On Edge)网:顾名思义,用边表示活动的网,当然它也是DAG。与AOV不同,活动都表示在了边上,如下图所示:
如上所示,共有11项活动(11条边),9个事件(9个顶点)。整个工程只有一个开始点和一个完成点。即只有一个入度为零的点(源点)和只有一个出度为零的点(汇点)。
关键路径:是从开始点到完成点的最长路径的长度。路径的长度是边上活动耗费的时间。如上图所示,1 到2 到 5到7到9是关键路径(关键路径不止一条,请输出字典序最小的),权值的和为18。
输入
这里有多组数据,保证不超过10组,保证只有一个源点和汇点。输入一个顶点数n(2<=n<=10000),边数m(1<=m <=50000),接下来m行,输入起点sv,终点ev,权值w(1<=sv,ev<=n,sv != ev,1<=w <=20)。数据保证图连通。
输出
关键路径的权值和,并且从源点输出关键路径上的路径(如果有多条,请输出字典序最小的)。
示例输入
9 11 1 2 6 1 3 4 1 4 5 2 5 1 3 5 1 4 6 2 5 7 9 5 8 7 6 8 4 8 9 4 7 9 2
示例输出
18 1 2 2 5 5 7 7 9
提示
#include<bits/stdc++.h>
using namespace std;
#define MAXN 10010
typedef struct ArcNode //链域
{
int adjvex;//弧所指的顶点
struct ArcNode *next;
int weight; //权值,表活动时间
}ArcNode;
typedef struct Vnode//顶点域
{
int data;
ArcNode *firstarc;//指向第一条依附该顶点的弧的指针
}Vnode,AdjList[MAXN];
typedef struct
{
AdjList vertices;
int vexnum,arcnum;//图当前的顶点数和弧数
}ALGraph;
int indegree[MAXN];
int ve[MAXN];
int vl[MAXN];
int create(ALGraph &g)
{
int i,j,k;
int u,v,w;
ArcNode *p;
for(i=1;i<=g.vexnum;i++)
{
g.vertices[i].firstarc=NULL;
}
memset(indegree,0,sizeof(indegree));
for(i=g.arcnum;i>=1;i--)
{
cin>>u>>v>>w;
p=new ArcNode;
indegree[v]++;
p->adjvex=v;
p->weight=w;
p->next=g.vertices[u].firstarc;
g.vertices[u].firstarc=p;
}
return 0;
}
stack<int >S2;
int CriticalPath(ALGraph g) //拓扑排序求最早发生时间ve[]
{
stack<int >S1;
ArcNode *p;
int cnt=0;//用于记录顶点数
memset(ve,0,sizeof(ve));
for(int i=1;i<=g.vexnum;i++)
{
if(indegree[i]==0)
S1.push(i);
}
while(!S1.empty())
{
int j=S1.top();
S1.pop();
S2.push(j);
cnt++;
p=g.vertices[j].firstarc;
while(p)
{
if((--indegree[p->adjvex])==0)
S1.push(p->adjvex);
if(ve[j]+p->weight>ve[p->adjvex])
{
ve[p->adjvex]=ve[j]+p->weight;
}
p=p->next;
}
}
/**
*用于检验最早发生时间是否正确
*/
/*for(int i=1;i<=g.vexnum;i++)
cout<<ve[i];*/
if(cnt==g.vexnum)
return 1;
else
return 0;
}
void CriticalActivity(ALGraph g) //逆拓扑排序求最迟发生时间vl[]
{
if(!CriticalPath(g)) return ;
ArcNode *p;
for(int i=1;i<=g.vexnum;i++)
{
vl[i]=ve[g.vexnum];
}
while(!S2.empty())
{
int j=S2.top();
S2.pop();
p=g.vertices[j].firstarc;
while(p)
{
if(vl[p->adjvex]-p->weight<vl[j])
{
vl[j]=vl[p->adjvex]-p->weight;
}
p=p->next;
}
}
cout<<ve[g.vexnum]<<endl;
ArcNode *q;
int a,b,flag=0;
/**
*用于检验关键活动是否正确
*/
/*for(int j=1;j<=g.vexnum;j++)
cout<<vl[j]<<endl;*/
for(int i=1;i<=g.vexnum;i++)
{
q=g.vertices[i].firstarc;
while(q) //求关键活动路径
{
int k=q->adjvex;
int ee=ve[i];
int el=vl[k]-q->weight;
if(ee==el) //找到关键活动路径并按要求输出
{
if(flag==0)
{
a=i;
b=k;
flag=1;
}
else if(a==i&&b>k)
b=k;
else if(b==i)
{
cout<<a<<" "<<b<<endl;
a=i;
b=k;
}
}
q=q->next;
}
}
cout<<a<<" "<<b<<endl;
}
int main()
{
ALGraph g;
while(cin>>g.vexnum>>g.arcnum)
{
create(g);
CriticalActivity(g);
}
return 0;
}