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 2Sample 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
//通过扫描边信息,每两个顶点之间都寻找最大边,记录路径即为关键路径