题意很简单,有N个城市,两两之间的距离用一个邻接矩阵给出。问题关键在于,找出最短路,并输出字典序最小的一条。以前一直也没想过这个问题,没想过怎么把最短的一条输出来。其实也不较简单,就是先用Floyd求得点对距离,在按照字典序dfs,把最短距离作为一个强剪枝来用,得到的第一个合法路径即为最短最小字典序路径。路径的输出可以用递归的形式来实现。
代码
#include<stdio.h>
#include<string.h>
#define INF 0xfffffff
#define NN 100
int N, S, T, ok;
int dis[NN][NN];
int map[NN][NN];
int mark[NN];
int pre[NN];
int cost[NN];
void floyd(){
int i, j, k;
memcpy(dis, map, sizeof(map));
for (k = 1; k <= N; k++){
for (i = 1; i <= N; i++){
for (j = 1; j <= N; j++){
if (dis[i][j] > dis[i][k] + dis[k][j] + cost[k]){
dis[i][j] = dis[i][k] + dis[k][j] + cost[k];
}
}
}
}
}
void dfs(int cur, int d){
int i, t;
if (d > dis[S][T]) return;
if (cur == T && d == dis[S][T]){
ok = 1;
return;
}
for (i = 1; i <= N; i++){
if (!mark[i]){
mark[i] = 1;
pre[i] = cur;
t = d + map[cur][i];
if (i != T){
t += cost[i];
}
dfs(i, t);
if (ok) return;
mark[i] = 0;
}
}
}
void out(int cur){
if (cur == S){
printf("%d", cur);
return;
}
out(pre[cur]);
printf("-->%d", cur);
}
int main()
{
int i, j, a, b;
//freopen("q1456.in", "r", stdin);
//freopen("a.out", "w", stdout);
while(scanf("%d", &N) != EOF){
if (N == 0) break;
for (i = 1; i <= N; i++){
for (j = 1; j <= N; j++){
scanf("%d", &a);
if (a == -1) a = INF;
map[i][j] = a;
}
}
for (i = 1; i <= N; i++){
scanf("%d", &cost[i]);
}
floyd();
while(scanf("%d%d", &a, &b) != EOF){
if (a == - 1 && b == -1) break;
S = a;
T = b;
ok = 0;
memset(mark, 0, sizeof(mark));
dfs(S, 0);
printf("From %d to %d :\nPath: ", a, b);
out(b);puts("");
printf("Total cost : %d\n", dis[a][b]);
puts("");
}
}
return 0;
}