ACM/ICPC 之 Floyd+记录路径后继(Hdu1385(ZOJ1456))

需要处理好字典序最小的路径

 


 

HDU1385(ZOJ1456)-Minimum Transport

 

 

//Hdu1385-ZOJ1456
//给定邻接矩阵,求给定起点到终点的最短路径,若有相同路长的路径按照字典序输出
//Floyd比较适合此题
//网上看到的两种做法比较推荐
//第一种是Floyd+记录起点后继
//第二种是Floyd+深搜(从起点开始深搜至终点)-利用Floyd得到的最短路剪枝
//其他的解法则是按照SPFA,dijkstra解,当路长相同时需要进行比较(较繁琐)
//Time:0Ms	Memory:404K
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;

#define INF 0x3f3f3f3f
#define MAX 105

int n;
int	d[MAX][MAX];
int board[MAX][MAX], c[MAX];
int path[MAX][MAX];	//记录i到j最短路径中i的后继

void floyd()
{
	memcpy(d, board, sizeof(d));
	for (int k = 1; k <= n; k++)
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
			{
				if (d[i][j] > d[i][k] + d[k][j] + c[k])
				{
					d[i][j] = d[i][k] + d[k][j] + c[k];
					path[i][j] = path[i][k];
				}
				//相同路径下选择后继更小的
				else if (d[i][j] == d[i][k] + d[k][j] + c[k] && path[i][j] > path[i][k])
					path[i][j] = path[i][k];
			}
}

void output(int s,int e)
{
	printf("-->%d", path[s][e]);
	if (path[s][e] != e)
		output(path[s][e], e);
}

int main()
{
	while (scanf("%d", &n), n)
	{
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
			{
				scanf("%d", &board[i][j]);
				if (board[i][j] == -1) board[i][j] = INF;
				path[i][j] = j;
			}
		for (int i = 1; i <= n; i++)
			scanf("%d", &c[i]);
		floyd();
		int s, e;
		while (scanf("%d%d", &s, &e), s != -1 && e != -1)
		{
			printf("From %d to %d :\n", s, e);
			printf("Path: %d", s);
			if(s != e)	output(s, e);	//起点与终点不同开始递归
			printf("\nTotal cost : %d\n\n", d[s][e]);
		}
	}
	return 0;
}

 

posted @ 2016-05-08 23:26  文字失效  阅读(281)  评论(0编辑  收藏  举报