HDU

题目链接
题目大意:给你一个邻接矩阵和每个点的权值,问你任意两点的最短路的花费以及路径。
  这个题途中经过某个点收费很好处理,只要在松弛的时候加上中间点的权值即可,但是打印路径就有些麻烦了。因为是多源最短路问题,所以我们不能像单源最短路那样用一维的数组来存前驱/后驱来打印路径了。
  我们可以用一个二维的数组来存每个路径的后驱,比如我们要计算1到3的最短路,而路径是1->5->4->3,那么我们只要知道1->3的下一步、5->3的下一步、4->3的下一步即可,因为要求字典序最小的路径,所以如果
路径长度相等的话需要选靠前面的最小的点作为后驱。

const int maxn = 1e3+10;
int n, p[maxn][maxn], cost[maxn], g[maxn][maxn];
void floyd() {
    for (int k = 1; k<=n; ++k)
        for (int i = 1; i<=n; ++i)
            if (g[i][k]!=INF)
                for (int j = 1; j<=n; ++j) {
                    int tmp = g[i][k]+g[k][j]+cost[k];
                    if (g[i][j]>tmp || (g[i][j]==tmp && p[i][j]>p[i][k])) {
                        p[i][j] = p[i][k];
                        g[i][j] = g[i][k]+g[k][j]+cost[k];
                    }
                }
}
void print_path(int a, int b) {
    printf("From %d to %d :
", a, b);
    printf("Path: %d", a);
    int next = a;
    while(next!=b) {
        next = p[next][b];
        printf("-->%d", next);
    }
    putchar(endl);
}
int main(void) {
    while(~scanf("%d", &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;
                else p[i][j] = j;
            }
        for (int i = 1; i<=n; ++i) scanf("%d", &cost[i]);
        floyd();
        int a, b;
        while(~scanf("%d%d", &a, &b) && (a!=-1&&b!=-1)) {
            print_path(a, b);
            printf("Total cost : %d

", g[a][b]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/shuitiangong/p/12591514.html