动态规划求AOE网的关键路径

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

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

Sample 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

Sample Output

18
1 2
2 5
5 7
7 9

#include<iostream>
using namespace std;

struct Node{//边
	int sv;//起点
	int ev;//终点
	int weight;//权值 
}; 


int main(){
	int vertexNum, arcNum;
	cin >> vertexNum >> arcNum;
	
	int *path = new int[vertexNum+1]();//记录每个顶点出发,最大权值路径的下一个点
	int *dis = new int[vertexNum+1]();//记录路径权值和
	int *inD = new int[vertexNum+1]();//记录每个顶点的入度数 
	Node *edge = new Node[arcNum];//记录边信息
	
	for(int i=0; i<arcNum; i++){
		cin >> edge[i].sv >> edge[i].ev >> edge[i].weight;
		inD[edge[i].ev]++;
	} 
	
	int start;//源点
	for(int i=1; i<=vertexNum; i++){
		if(inD[i] == 0){
			start = i;
			break;
		}
	}
	
	//动态规划求关键路径,dis[start]存储着路径权值
	for(int i=0; i<vertexNum-1; i++){//最长(n-1),所以更新(n-1)次
		//实际不一定需要(n-1)次,所以用一个标记跳出循环 
		int temp = 0; 
		for(int j=0; j<arcNum; j++){//以边为循环对象
			if(dis[edge[j].sv] < dis[edge[j].ev] + edge[j].weight || (dis[edge[j].sv]) == dis[edge[j].ev] + edge[j].weight && path[edge[j].sv] > edge[j].ev){
				dis[edge[j].sv] = dis[edge[j].ev] + edge[j].weight;
				path[edge[j].sv] = edge[j].ev;
				temp = 1;
			} 
		}
		if(temp == 0){//更新结束 
			break;
		}
	} 
	
	//输出
	cout << dis[start] << endl;
	int k = start;
	while(path[k]){
		cout << k << " " << path[k] << endl;
		k = path[k];
	} 
	
	return 0;
}
//思路:动态规划求关键路径
//有n个顶点,关键路径最长为n-1
//通过扫描边信息,每两个顶点之间都寻找最大边,记录路径即为关键路径 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值