数据结构实验之图论:AOE网上的关键路径

数据结构实验之图论十一:AOE网上的关键路径

Time Limit: 1000MS Memory Limit: 65536KB

SubmitStatistic

Problem Description

    一个无环的有向图称为无环图(Directed Acyclic Graph),简称DAG图。
    AOE(Activity On Edge)网:顾名思义,用边表示活动的网,当然它也是DAG。与AOV不同,活动都表示在了边上,如下图所示:
                                     
    如上所示,共有11项活动(11条边),9个事件(9个顶点)。整个工程只有一个开始点和一个完成点。即只有一个入度为零的点(源点)和只有一个出度为零的点(汇点)。
    关键路径:是从开始点到完成点的最长路径的长度。路径的长度是边上活动耗费的时间。如上图所示,1 到2 到 5到7到9是关键路径(关键路径不止一条,请输出字典序最小的),权值的和为18。

Input

    这里有多组数据,保证不超过10组,保证只有一个源点和汇点。输入一个顶点数n(2<=n<=10000),边数m(1<=m <=50000),接下来m行,输入起点sv,终点ev,权值w(1<=sv,ev<=n,sv != ev,1<=w <=20)。数据保证图连通。

Output

    关键路径的权值和,并且从源点输出关键路径上的路径(如果有多条,请输出字典序最小的)。

Example Input

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

Example Output

18
1 2
2 5
5 7
7 9
#include <bits/stdc++.h> 
using namespace std; 
typedef struct arcnode//表结点 
{
   int adj;//存储结点;
   arcnode *next; 
   int info;//存储权值; 
} arcnode; 
typedef struct vnode//头结点; 
{
    int data; 
    arcnode *head; 
} adjlist[10001]; 
typedef struct//图的结构 
{ 
   adjlist a; 
   int vexn,arcn; // 结点数 边数 
} MG; 
   int i,j; 
   int indegree[10001];//记录每个点的入度 
   int ve[10001];//最早开始时间; 
   int vl[10001];//最迟开始时间; 
void create(MG &G)//建立有向图邻接表; 
{ 
    int v1,v2,w; 
	arcnode *p;
	for(i=1; i<=G.vexn; i++)  
	G.a[i].head=NULL;//头结点清空;
	for(i=1; i<=G.arcn; i++) {
	  cin >> v1 >> v2 >> w; 
	  p=new arcnode;  
	  p->adj=v2;  
	  p->info=w; 
	  indegree[v2]++; 
	  p->next=G.a[v1].head; 
	  G.a[v1].head=p; 
	 } 
}
 stack<int>s;//用于逆拓扑有序时求vl; 
 int topo1(MG &G)//求ve(最早开始时间即最大路径长度); 
 { 
    int k; 
	arcnode *p; 
	stack<int>t; 
	for(i=1; i<=G.vexn; i++) 
	if(!indegree[i])//入度为零的结点入栈
	      t.push(i); 
	memset(ve,0,sizeof(ve));//初始化最早开始时间; 
	int count=0;//记录出栈元素个数,判定拓扑排序是否有序; 
	while(!t.empty())
	{ 
	    j=t.top(); 
		t.pop(); 
		s.push(j); 
		count++;  
		for(p=G.a[j].head; p; p=p->next) 
		{ 
		    k=p->adj; 
			if(!(--indegree[k]))//将新入度为零的节点进栈; 
			   t.push(k); 
			if(ve[j]+p->info>ve[k])//更新最大路径长度; 
			   ve[k]=ve[j]+p->info; 
		} 
	} 
	if(count<G.vexn)//拓扑不是有序的,即有环; 
	     return 0; 
	return 1; 
} 
int topo2(MG &G)//求vL(既不影响施工进度的情况下最晚的开始时间; 
{ 
    int k; 
	arcnode *p; 
	if(!topo1(G)) return 0;//拓扑无序,则结束; 
	cout <<  ve[G.vexn] << endl;//关键路径的权值和; 
	for(i=1; i<=G.vexn; i++) //初始化最迟开始时间; 
	vl[i]=ve[G.vexn]; 
	while(!s.empty())//按拓扑逆序求vl; 
	{ 
	    j=s.top(); 
		s.pop(); 
		for(p=G.a[j].head; p; p=p->next)
		{ 
		    k=p->adj;  
			if(vl[k]-p->info<vl[j])//更新最晚开始时间; 
			   vl[j]=vl[k]-p->info; 
		} 
	} 
	int flag=0,a,b;
	for(j=1; j<=G.vexn; j++) //求关键活动; 
	  for(p=G.a[j].head; p; p=p->next) 
	   { 
	       k=p->adj; 
		   int e=ve[j]; 
		   int l=vl[k]-p->info; 
		   if(e==l)//关键路径要求最早开始时间和最晚开始时间相同没有空余时间; 
		   { 
		      if(flag==0)//对输出的特殊处理,要求字典序最小 
			   { 
			       a=j; 
				   b=k; 
				   flag=1;  
				} 
			  else if(a==j&&b>k) 
			     b=k; 
			  else if(b==j)//结束活动的分支时b作为活动的开始时。 
			   { 
			      printf("%d %d\n",a,b); 
				  a=j; 
				  b=k; 
				} 
			}  
		} 
		cout << a << " " << b << endl; 
		return 1; 
} 
int main() { 
     MG G; 
	 while(cin >> G.vexn >> G.arcn) 
	 { 
	     memset(indegree,0,sizeof(indegree)); 
		 create(G);
		 topo2(G); 
	}
      return 0; 
}
 
 
 
 
 
 
 

 

 
 
 
 
 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值