0
点赞
收藏
分享

微信扫一扫

【ACWing】4196. 最短路径

c一段旅程c 2022-05-01 阅读 58

题目地址:

https://www.acwing.com/problem/content/description/4199/

给定一个 n n n个点 m m m条边的的无向图。点的编号从 1 1 1 n n n。图中可能包含重边和自环。请你找到并输出一条从点 1 1 1到点 n n n的最短路径。

输入格式:
第一行包含两个整数 n , m n,m n,m。接下来 m m m行,每行包含三个整数 a , b , w a,b,w a,b,w,表示点 a a a和点 b b b之间存在一条无向边,边长为 w w w

输出格式:
如果最短路径不存在,则输出 − 1 −1 1。否则,在一行内输出从点 1 1 1到点 n n n的最短路径中依次包含的点的编号,各点编号之间用空格隔开。如果答案不唯一,输出任意合理方案均可。

数据范围:
前六个测试点满足 2 ≤ n ≤ 10 2≤n≤10 2n10 1 ≤ m ≤ 10 1≤m≤10 1m10
所有测试点满足 2 ≤ n ≤ 1 0 5 2≤n≤10^5 2n105 1 ≤ m ≤ 1 0 5 1≤m≤10^5 1m105 1 ≤ a , b ≤ n 1≤a,b≤n 1a,bn 1 ≤ w ≤ 1 0 6 1≤w≤10^6 1w106
本题不卡spfa算法。

直接用Dijkstra算法。如果存在解的话,则在Dijkstra树上从 1 1 1 n n n的路径即为一个合法路径。可以用pre数组来记录每个点由谁更新而来,从而把路径记下来。最后输出路径的时候从 n n n倒着推回去即可。代码如下:

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
using PLI = pair<long, int>;

const int N = 1e5 + 10, M = 2e5 + 10;
int n, m;
int h[N], e[M], ne[M], w[M], idx;
long dist[N];
int pre[N];
bool vis[N];
int res[N];

void add(int a, int b, int c) {
  e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

void dijkstra() {
  memset(dist, 0x3f, sizeof dist);
  dist[1] = 0;
  priority_queue<PLI, vector<PLI>, greater<>> heap;
  heap.push({0, 1});
  pre[1] = 1;
  while (heap.size()) {
    auto t = heap.top(); heap.pop();
    int v = t.second;
    if (vis[v]) continue;
    // 到了n号点了,找到了到n的最短路,退出
    if (v == n) break;
    vis[v] = true;
    for (int i = h[v]; ~i; i = ne[i]) {
      int j = e[i];
      if (dist[j] > dist[v] + w[i]) {
        dist[j] = dist[v] + w[i];
        pre[j] = v;
        heap.push({dist[j], j});
      }
    }
  }
}

int main() {
  memset(h, -1, sizeof h);
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; i++) {
    int a, b, c;
    scanf("%d%d%d", &a, &b, &c);
    add(a, b, c), add(b, a, c);
  }

  dijkstra();
  if (dist[n] == 0x3f3f3f3f3f3f3f3f) puts("-1");
  else {
    int cnt = 0;
    while(n != 1) {
      res[cnt++] = n;
      n = pre[n];
    }
    res[cnt++] = 1;
    // 倒着输出,得出路径
    for (int i = cnt - 1; i >= 0; i--) printf("%d ", res[i]);
  }
}

时间复杂度 O ( m log ⁡ n ) O(m\log n) O(mlogn),空间 O ( n ) O(n) O(n)

举报

相关推荐

0 条评论