最短路:路径还原(dijkstra,模板)

在wzy的冒险旅程中,他需要从第一个城镇走到最后一个城镇。本篇介绍了一个算法,帮助wzy找到从起点到终点的最短路径,并以倒序方式输出路径。通过使用Dijkstra算法,我们能够有效地解决这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

B. wzy的大冒险——出发咯QAQ

单点时限: 2.0 sec

内存限制: 512 MB

wzy踏上了冒险的旅程。
现在他从地精手里买了一份地图,地图上有n个城镇。
他从第一个城镇出发,走向(没钱只能走)第n个城镇,现在,请你帮wzy找到一条最短的路径,并倒序(从n到1)输出一条最短路径。
举个栗子:如果有两条路径6 4 3 1和6 5 2 1,我们选择6 4 3 1这条。
地精小提示:路是单向的QAQ。

输入格式

第一行两个数n,m ,(1≤n≤103,1≤m≤103)

接下来m行,每行三个数x,y,z,表示点 x 与点 y 之间有一条权值为 z 的有向边 (1≤x,y,z≤103).

输出格式

第一行一个整数表示 1 到 n 的最短距离;
第二行倒序输出这条路径。

样例

input

5 7
1 2 69
1 3 87
1 4 79
2 5 94
2 3 10
3 5 79
4 5 43

output

122
5 4 1
#include <bits/stdc++.h>

using namespace std;
const int N = 1010;
const int INF = 0x3f3f3f3f;

int cost[N][N]; // 存图
int used[N];    // 标记边是否用过
int dis[N];     // 起点到其他点的最短距离
int prevs[N];   // 存最短路上每个点的前驱点
int n, m;

void djk(int s)
{
    memset(used, 0, sizeof(used));
    memset(dis, 0x3f, sizeof(dis));
    memset(prevs, -1, sizeof(prevs));
    dis[s] = 0;

    while(1)
    {
        int v = -1;
        for(int i=1; i <= n; i++)
        {
            if(!used[i] && (v == -1 || dis[i] < dis[v]))
                v = i;
        }
        if(v == -1) break;
        used[v] = 1;
        for(int i=1; i <= n; i++)
        {
            if(dis[i] > dis[v] + cost[v][i])
            {
                dis[i] = dis[v] + cost[v][i];
                prevs[i] = v;    // 保存最短路上下一个节点的前驱
            }
        }
    }
}

vector<int> get_path(int t) // 得到的最短路是逆序的
{
    vector<int> path;
    for( ; t != -1; t = prevs[t])
        path.push_back(t);
    return path;
}


int main()
{
    while(scanf("%d %d", &n, &m) != EOF)
    {
        memset(cost, INF, sizeof(cost));
        int a, b, c;
        for(int i=0; i<m; i++)
        {
            scanf("%d %d %d", &a, &b, &c);
            cost[a][b] = c;
            // cost[b][a] = c;      // 如果边是双向的就加入
        }
        djk(1);
        vector<int> ve = get_path(n);
        int len = ve.size();
        printf("%d\n", dis[n]);
        for(int i=0; i<len; i++)
        {
            printf("%d%c", ve[i], i == len-1 ? '\n' : ' ');
        }
    }



    return 0;
}

 

# P5905 【模板】全源短路(Johnson) ## 目描述 给定一个包含 $n$ 个结点和 $m$ 条带权边的有向图,求所有点对间的最短路径长度,一条路径的长度定义为这条路径上所有边的权值和。 注意: 1. 边权**可能**为负,且图中**可能**存在重边和自环; 2. 部分数据卡 $n$ 轮 SPFA 算法。 ## 输入格式 第 $1$ 行:$2$ 个整数 $n,m$,表示给定有向图的结点数量和有向边数量。 接下来 $m$ 行:每行 $3$ 个整数 $u,v,w$,表示有一条权值为 $w$ 的有向边从编号为 $u$ 的结点连向编号为 $v$ 的结点。 ## 输出格式 若图中存在负环,输出仅一行 $-1$。 若图中不存在负环: 输出 $n$ 行:令 $dis_{i,j}$ 为从 $i$ 到 $j$ 的短路,在第 $i$ 行输出 $\sum\limits_{j=1}^n j\times dis_{i,j}$,注意这个结果可能超过 int 存储范围。 如果不存在从 $i$ 到 $j$ 的路径,则 $dis_{i,j}=10^9$;如果 $i=j$,则 $dis_{i,j}=0$。 ## 输入输出样例 #1 ### 输入 #1 ``` 5 7 1 2 4 1 4 10 2 3 7 4 5 3 4 2 -2 3 4 -3 5 3 4 ``` ### 输出 #1 ``` 128 1000000072 999999978 1000000026 1000000014 ``` ## 输入输出样例 #2 ### 输入 #2 ``` 5 5 1 2 4 3 4 9 3 4 -3 4 5 3 5 3 -2 ``` ### 输出 #2 ``` -1 ``` ## 说明/提示 【样例解释】 左图为样例 $1$ 给出的有向图,短路构成的答案矩阵为: ``` 0 4 11 8 11 1000000000 0 7 4 7 1000000000 -5 0 -3 0 1000000000 -2 5 0 3 1000000000 -1 4 1 0 ``` 右图为样例 $2$ 给出的有向图,红色标注的边构成了负环,注意给出的图不一定连通。 ![](https://cdn.luogu.com.cn/upload/image_hosting/7lb35u4u.png) 【数据范围】 对于 $100\%$ 的数据,$1\leq n\leq 3\times 10^3,\ \ 1\leq m\leq 6\times 10^3,\ \ 1\leq u,v\leq n,\ \ -3\times 10^5\leq w\leq 3\times 10^5$。 对于 $20\%$ 的数据,$1\leq n\leq 100$,不存在负环(可用于验证 Floyd 正确性) 对于另外 $20\%$ 的数据,$w\ge 0$(可用于验证 Dijkstra 正确性) upd. 添加一组 Hack 数据:针对 SPFA 的 SLF 优化
最新发布
07-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值