Minimum Transport Cost(HDU 1385)---后驱存储路径

题目链接

题目描述

These are N cities in Spring country. Between each pair of cities there may be one transportation track or none. Now there is some cargo that should be delivered from one city to another. The transportation fee consists of two parts:
The cost of the transportation on the path between these cities, and
a certain tax which will be charged whenever any cargo passing through one city, except for the source and the destination cities.
You must write a program to find the route which has the minimum cost.

输入格式

First is N, number of cities. N = 0 indicates the end of input.
The data of path cost, city tax, source and destination cities are given in the input, which is of the form:
a11 a12 … a1N
a21 a22 … a2N

aN1 aN2 … aNN
b1 b2 … bN
c d
e f

g h
where aij is the transport cost from city i to city j, aij = -1 indicates there is no direct path between city i and city j. bi represents the tax of passing through city i. And the cargo is to be delivered from city c to city d, city e to city f, …, and g = h = -1. You must output the sequence of cities passed by and the total cost which is of the form:

输出格式

From c to d :
Path: c–>c1–>…–>ck–>d
Total cost : …

From e to f :
Path: e–>e1–>…–>ek–>f
Total cost : …
Note: if there are more minimal paths, output the lexically smallest one. Print a blank line after each test case.

输入样例

5
0 3 22 -1 4
3 0 5 -1 -1
22 5 0 9 20
-1 -1 9 0 4
4 -1 20 4 0
5 17 8 3 1
1 3
-1 -1
0

输出样例

From 1 to 3 :
Path: 1–>5–>4–>3
Total cost : 21

分析

题目大意是有n个城市,经过任意一个城市不仅要交税,还要路线上的运输费用, 现在要求从a城市到b城市的最小费用,以及最下距离下的按字典序的路径。考虑到题目中有多组查询,因此使用floyd算法,另外由于需要字典序最小路径,就需要后驱存储,因为前驱存储无法保证字典序,以下是源码。

源程序

Floyd算法

#include <bits/stdc++.h>
#define MAXN 105
#define INF 1e9
using namespace std;
int n,x,y,g[MAXN][MAXN],point[MAXN],path[MAXN][MAXN];
void floyd()
{
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++){
				if(g[i][k]==INF||g[k][j]==INF)continue;	//不存在边 
				int tmp=g[i][k]+g[k][j]+point[k];
				if(g[i][j]>tmp){	//新的最小值 
					g[i][j]=tmp;
					path[i][j]=path[i][k];
				}
				else if(g[i][j]==tmp&&path[i][j]>path[i][k]){	//最小值相等但从i出发的路径更小 
					path[i][j]=path[i][k];
				}
			}
					
}
int main()
{
	while(scanf("%d",&n)&&n){
		for(int i=1;i<=n;i++){	//读入数据 
			for(int j=1;j<=n;j++){
				scanf("%d",&g[i][j]);
				if(g[i][j]==-1)g[i][j]=INF;	
				path[i][j]=j;	//初始化path数组 
			}
		}
		for(int i=1;i<=n;i++)scanf("%d",&point[i]);	//读入点数 
		floyd();
		while(scanf("%d%d",&x,&y)){
            if(x==-1&&y==-1) break;
            printf("From %d to %d :\n",x,y);
            printf("Path: ");
            int u=x;
            printf("%d",u);
            while(u!=y){	//后驱 
                printf("-->%d",path[u][y]);
                u=path[u][y];
            }
            printf("\nTotal cost : %d\n\n", g[x][y]);
        }
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值