首页 > 编程语言 >最短路算法(总结性,无Dij)

最短路算法(总结性,无Dij)

时间:2024-07-16 23:19:48浏览次数:14  
标签:std distance 总结性 Dij int 短路 cin edge dis

Floyd

利用中介点k进行操作

记f[x][y]为xy点之间的最短路径长度

其中f[x][y] = min(f[x][y], f[x][k] + f[k][y]);

即用k进行松弛操作

其中f[x][y]的取值

  • 当xy有直接连边时:f[x][y]=w(x,y)

    当无直接连边时:f[x][y]=+∞

    当x=y时:f[x][y]=0

实现:

for (k = 1; k <= n; k++) {
  for (x = 1; x <= n; x++) {
    for (y = 1; y <= n; y++) {
      f[x][y] = min(f[x][y], f[x][k] + f[k][y]);
    }
  }
}

Bellman-Ford

松弛操作:

对于边u,v

松弛操作如下:

dis(v)=min(dis(v),dis(u,v))

这么做目的很明显,通过s→u的最短路+w(u,v)来更新s→v的最短路

实现:

#include <iostream>
#include <cstring>

using namespace std;
#define INF 0x7f7f7f7f

struct Edge{
    int u, v, w;
}edge[1000005];
int n, m, s, u, v, w, cnt,dis[10005];

void BellmanFord(){
    memset(dis, 0x7f, sizeof(dis));
    dis[s] = 0;
    for (int i = 1; i <= n;i++)
        for (int j = 1; j <= cnt;j++){
            int u = edge[j].u, v = edge[j].v, w = edge[j].w;
            if(dis[u]==INF)
                continue;
            if(dis[v]>dis[u]+w)
                dis[v] = dis[u] + w;
        }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n >> m >> s;
    while(m--){
        cin >> u >> v >> w;
        edge[++cnt].u = u;
        edge[cnt].v = v;
        edge[cnt].w = w;
    }
    BellmanFord();
    for (int i = 1; i <= n;i++)
        if (dis[i] == INF)
            cout << 2147483647 << ' ';
        else
            cout << dis[i] << ' ';
    return 0;
}
//判断负环的BellmanFord
struct Edge {
  int u, v, w;
};

vector<Edge> edge;

int dis[MAXN], u, v, w;
const int INF = 0x3f3f3f3f;

bool bellmanford(int n, int s) {
  memset(dis, 0x3f, sizeof(dis));
  dis[s] = 0;
  bool flag = false;  // 判断一轮循环过程中是否发生松弛操作
  for (int i = 1; i <= n; i++) {
    flag = false;
    for (int j = 0; j < edge.size(); j++) {
      u = edge[j].u, v = edge[j].v, w = edge[j].w;
      if (dis[u] == INF) continue;
      // 无穷大与常数加减仍然为无穷大
      // 因此最短路长度为 INF 的点引出的边不可能发生松弛操作
      if (dis[v] > dis[u] + w) {
        dis[v] = dis[u] + w;
        flag = true;
      }
    }
    // 没有可以松弛的边时就停止算法
    if (!flag) {
      break;
    }
  }
  // 第 n 轮循环仍然可以松弛时说明 s 点可以抵达一个负环
  return flag;
}

基于BellmanFord的SPFA

先给出标程:

#include <iostream>
#include <queue>
#include <cstring>

struct {
    int to, edgeWeight,next;
}edge[500005];
int head[10005], counter, distance[10005], s, n, m;

void addEdge(int u, int v,int edgeWeight) {
    edge[++counter].to = v;
    edge[counter].edgeWeight = edgeWeight;
    edge[counter].next = head[u];
    head[u] = counter;
}

void SPFA() {
    memset(distance, 0x7f, sizeof(distance));
    distance[s] = 0;
    std::queue<int> q;
    q.push(s);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = head[u];i != 0;i = edge[i].next) {
            int v = edge[i].to, w = edge[i].edgeWeight;
            if (distance[v] > distance[u] + w) {
                distance[v] = distance[u] + w;
                q.push(v);
            }
        }
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    std::cin >> n >> m >> s;
    while (m--) {
        int u, v, weight;
        std::cin >> u >> v >> weight;
        addEdge(u, v, weight);
    }
    SPFA();
    for (int i = 1;i <= n;i++)(distance[i] == 0x7f7f7f7f || distance[i] == 0) && i != s ? std::cout << "2147483647 " : std::cout << distance[i] << ' ';
    return 0;
}

同理dis(v)=min(dis(v),dis(u,v))

不过将可以被松弛的节点放到了q这个队列中,同时存图变为了链式前向星

容易被卡

标签:std,distance,总结性,Dij,int,短路,cin,edge,dis
From: https://www.cnblogs.com/PanGZ-cabin/p/18306318

相关文章

  • 代码随想录算法训练营第六十六天 | Bellman_ford 队列优化算法(SPFA)、Bellman_ford之
    Bellman_ford队列优化算法(SPFA)题目链接:https://kamacoder.com/problempage.php?pid=1152文档讲解:https://programmercarl.com/kamacoder/0094.%E5%9F%8E%E5%B8%82%E9%97%B4%E8%B4%A7%E7%89%A9%E8%BF%90%E8%BE%93I-SPFA.html思路Bellman_ford算法每次松弛都是对所......
  • 代码随想录算法训练营第六十五天 | dijkstra(堆优化版)精讲、Bellman_ford 算法精讲、复
    dijkstra(堆优化版)精讲—卡码网:47.参加科学大会题目链接:https://kamacoder.com/problempage.php?pid=1047文档讲解:https://programmercarl.com/kamacoder/0047.%E5%8F%82%E4%BC%9Adijkstra%E5%A0%86.html思路当节点数多,边数少(稀疏图)时,可以考虑从边的角度出发,用堆来......
  • 次短路问题(最短路)
    https://www.luogu.com.cn/problem/P1491第5题   次短路问题 查看测评数据信息平面直角坐标系中有n个点,m条边,第i个点的坐标是(x[i],y[i]),求编号为1的点到编号为n的点第二最短路线的距离(保留两位小数),如果存在多条第一短路径,则答案就是第一最短路径的长度;数据没有重边,可能......
  • 【模板】单源最短路径(弱化版)
    【模板】单源最短路径(弱化版)洛谷P3371题目背景本题测试数据为随机数据,在考试中可能会出现构造数据让SPFA不通过,如有需要请移步P4779。题目描述如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。输入格式第一行包含三个整数......
  • 最大值(最短路+最短路计数)
    洛谷CF449B 第1题   最大值 查看测评数据信息给定一个包含n个点和m条边的无向图,以及k条特殊的直接连接节点1的边。每条边都有一个权重,表示两点之间的距离。现在,我们想知道最多可以移除这k条特殊边中的多少条,而保持图中每个节点到节点1的最短距离不变。 输入格......
  • 最短路问题
    最短路问题writeashortintroduce朴素做法writesomethingCode1Code多源最短路比较好于理解与编写的是Floyd算法。Code2#include<iostream>#include<iomanip>#include<string.h>usingnamespacestd;intn,m;intg[105][105];voidaddedge(intu,intv,int......
  • BFS:边权相同的最短路问题
    一、边权相同最短路问题简介二、迷宫中离入口最近的出口.-力扣(LeetCode)classSolution{public:constintdx[4]={1,-1,0,0};constintdy[4]={0,0,1,-1};intnearestExit(vector<vector<char>>&maze,vector<int>&e){intm=maze.size(),n=......
  • 单源最短路
    ABC340DSuperTakahashiBros.问题描述高桥正在玩一个游戏。这个游戏由编号为\(1,2,\ldots,N\)的\(N\)个阶段组成。最初,只有阶段\(1\)是可以玩的。对于每个可以玩的阶段\(i\)(其中\(1\leqi\leqN-1\)),在阶段\(i\)你可以执行以下两个动作之一:花费\(A_i\)秒来通过阶段\(i......
  • 单/全最短路专题 两题
    GregandGraph(Floyd)题意:Greg有一个n个点是一个有边权的有向图这个图两个点都有不一样的边(也就意味着a->b和b->a的权值是不一样的)每次操作都会删除一个点,让这个点和其他和它有关系的点都删除.对于每次删除操作,输出操作以前的最短路径之和思路:这一题的思路......
  • 参加科学大会-卡玛(堆优化版Dijkstra)
    学习参考:代码随想录与Prim类似,当节点数目较多,边的数量很小的时候(稀疏图),可以考虑从边的角度来求最短路,邻接矩阵遇到稀疏图,会导致申请过大的二维数组造成空间浪费且遍历边的时候需要遍历整个n*n矩阵,造成时间浪费。这时使用邻接链表明显更加符合需求。而在朴素版Dijk......