昨天晚上做这个题目到1点钟也没有发现错误,后来火大,果断重新开始写,今天下午终于AC。。算法为floyd+dfs,先使用floyd求出最短路,然后从起点开始深搜到终点并且记录路径,由于i从1开始遍历,因此所找到的第一条最短路路即为字典序最小路径,需要注意一下终点没有税,而且只需要输出字典序最小的那一条路。
AC代码如下:
#include <iostream>
using namespace std;
const int len = 110;
#define MAX1 0xfffffff
int dis[len][len];
int map[len][len];
int tax[len];
int path[len];
int visited[len];
int S, E;
int size;
int n;
void Floyd()
{
int i, j, k;
for (k = 1; k <= n; k ++){
for (i = 1; i <= n; i ++){
for (j = 1; j <= n; j ++){
if (dis[i][k]+dis[k][j]+tax[k] < dis[i][j]){
dis[i][j] = dis[i][k]+dis[k][j]+tax[k];
}
}
}
}
}
int check;
void Dfs(int deep, int sum)
{
if (sum > dis[S][E])return ;
if (sum == dis[S][E] && deep == E){
printf("Path: %d", S);
for (int i = 0; i < size; i ++){
printf("-->%d", path[i]);
}
printf("/n");
check = 1;
return ;
}
for (int i = 1; i <= n; i ++){
if (!visited[i]){
if (map[deep][i] != MAX1){
visited[i] = 1;
sum += map[deep][i];
if (i != E){
sum += tax[i];
}
path[size ++] = i;
Dfs(i, sum);
size --;
if (check)return ;
visited[i] = 0;
sum -= map[deep][i];
if (i != E){
sum -= tax[i];
}
}
}
}
}
int main()
{
while ( scanf("%d", &n) && n){
for (int i = 1; i <= n; i ++){
for (int j = 1; j <= n; j ++){
scanf("%d", &map[i][j]);
if (map[i][j] == -1){
map[i][j] = MAX1;
}
dis[i][j] = map[i][j];
}
}
for (int i = 1; i <= n; i ++){
scanf("%d", &tax[i]);
}
Floyd();
while (scanf("%d %d", &S, &E)&& S+E != -2){
check = 0;
printf("From %d to %d :/n", S, E);
memset(visited, 0, sizeof(visited));
Dfs(S, 0);
printf("Total cost : %d/n/n", dis[S][E]);
}
}
return 0;
}