T1-F 最短路

题目描述:

给定一个包含 n (e3)个结点和 m 条带权边的有向图,求所有点对间的最短路径长度,一条路径的长度定义为这条路径上所有边的权值和。

题目解析:

多源最短路的模板题,

  1. Floyd:时间复杂度为 O(n^3),能够解决负权边,不能解决负环,缺点就是很慢,不过此题放大了时间限制,floyd也可以过,模板如下。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
     
    ll dp[505][505];
     
    int main() {
      int n, m, p;
      scanf("%d%d%d", &n, &m, &p);
      for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
          dp[i][j] = LONG_LONG_MAX;
        }
        dp[i][i] = 0;
      }
      for (int i = 0; i < m; ++i) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        dp[u][v] = min(dp[u][v], ll(w));
      }
      for (int k = 1; k <= n; ++k) {
        for (int i = 1; i <= n; ++i) {
          for (int j = 1; j <= n; ++j) {
            if (dp[i][k] != LONG_LONG_MAX && dp[k][j] != LONG_LONG_MAX &&
                dp[i][k] + dp[k][j] < dp[i][j]) {
              dp[i][j] = dp[i][k] + dp[k][j];
            }
          }
        }
      }
      while (p--) {
        int u, v;
        scanf("%d%d", &u, &v);
        printf("%lld\n", dp[u][v] == LONG_LONG_MAX ? -1 : dp[u][v]);
      }
      return 0;
    }

    2.Dijkstra:以每个点为源点做一次 Dijkstra,时间复杂度为 O(nmlogn),时间上可以过,但是 Dijkstra 只能解决非负权边,一旦出现负权边就得另想办法,本题也可以过,模板如下。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
     
    const ll inf = LLONG_MAX / 2;
    const int maxv = 1e5 + 5;
     
    struct edge {
      int to;
      ll w;
      edge(int a, ll b) : to(a), w(b) {}
    };
    struct qnode {
      int id;
      ll ndis;
      qnode(int a, ll b) : id(a), ndis(b) {}
      bool operator<(const qnode& a) const { return ndis > a.ndis; }
    };
     
    vector<edge> g[maxv];
    int n, m;
    ll dis[maxv];
    bool done[maxv];
     
    void dijkstra(int s) {
      for (int i = 1; i <= n; ++i) {
        dis[i] = inf;
        done[i] = false;
      }
      dis[s] = 0;
      priority_queue<qnode> q;
      q.push(qnode(s, 0));
      while (!q.empty()) {
        qnode u = q.top();
        q.pop();
        if (done[u.id]) continue;
        done[u.id] = true;
        for (auto v : g[u.id]) {
          if (done[v.to]) continue;
          if (dis[v.to] > u.ndis + v.w) {
            dis[v.to] = u.ndis + v.w;
            q.push(qnode(v.to, dis[v.to]));
          }
        }
      }
    }
     
    int main() {
      // freopen("D:/Workspace/algo/E5-D/data/5.in", "r", stdin);
      int p, x, y;
      scanf("%d%d", &n, &m);
      scanf("%d%d%d", &p, &x, &y);
      for (int i = 0; i < m; ++i) {
        int u, v, t;
        scanf("%d%d%d", &u, &v, &t);
        g[u].push_back(edge(v, t));
        g[v].push_back(edge(u, t));
      }
    }

    每次dijkstra(p),dis数组都会储存p到其余n个点的最短路。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值