/**********************************/
/* 多段图问题 */
/*求源点到汇点的最小花费及最短路径*/
/**********************************/
#include<iostream>
#include<stdlib.h>
#include<malloc.h>
#define MAX 100 /*最大顶点数为100*/
using namespace std;
typedef struct NODE{ /*边表结点*/
int v_num; /*邻接点域*/
int len; /*邻接顶点与下个邻接顶点的费用*/
struct NODE * next; /*指向下个邻接顶点的指针*/
}EdgeNODE;
int main(){
/*函数声明*/
void create_graph(EdgeNODE NODE[], int n, int e);
int fgraph(EdgeNODE NODE[], int cost[], int route[], int path[], int n);
void show_route(int route[]);
int n, e; /*顶点数n,边数e*/
cout << "请输入图的顶点数和边数:";
cin >> n >> e;
EdgeNODE * NODE = new EdgeNODE[n]; //多段图邻接表头节点
int * cost = new int[n]; //在阶段决策中,各个顶点到收点的最小费用
int * route = new int[n]; //从源点到收点的最短路径上的顶点编号
int * path = new int[n];
/*在阶段决策中,各个顶点到收点的最短路径上的前方顶点编号*/
create_graph(NODE, n, e); //创建图的邻接表
cout << endl<<"顶点到收点的最小花费为:";
cout<<fgraph(NODE, cost, route, path, n); //输出最短路径费用
cout <<endl<< "路径为:";
show_route(route); //输出最短路径
system("pause");
return 0;
}
/*创建图的邻接表*/
void create_graph(EdgeNODE NODE[], int n, int e){
EdgeNODE * p;
for (int k = 0; k< n; k++){
NODE[k].v_num = k;
NODE[k].len = 0;
NODE[k].next = NULL;
}
cout <<endl<< "请输入"<<e<<"条边<i,j>和路径长度w:\n";
int i, j, w; //i为边起点,j为边终点,w为边权值
for (int t = 0; t < e; t++){
cin >> i >> j >> w; //输入边首尾点编号及其权值
p = (EdgeNODE *)malloc(sizeof(EdgeNODE));
p->v_num = j;
p->len = w;
p->next = NODE[i].next;
NODE[i].next = p;
}
}
/*求最短路径费用*/
int fgraph(EdgeNODE NODE[], int cost[], int route[], int path[], int n){
EdgeNODE * pnode;
// 初始化
for (int i = 0; i < n; i++){
cost[i] = MAX;
route[i] = 0;
path[i] = -1;
}
cost[n - 1] = 0;
for (int i = n - 2; i >= 0; i--){
/*计算各个顶点到收点的最短费用,并确定各个顶点到收点的
最小花费路径的前方顶点*/
pnode = NODE[i].next;
while (pnode != NULL){
if (pnode->len + cost[pnode->v_num] < cost[i]){
cost[i] = pnode->len + cost[pnode->v_num];
path[i] = pnode->v_num;
}
pnode = pnode->next;
}
}
/*从源点开始,递推的确定其前方顶点,直到收点为止*/
int j = 0; //源点为0
while ((route[j] != n - 1) && (path[j] != -1)){
j++;
route[j] = path[route[j-1]];
}
return cost[0];
}
/*打印最短路径*/
void show_route(int route[]){
cout << route[0];
for (int i = 1; route[i] != NULL;i++)
cout << "-->" << route[i];
cout << endl;
}