最短路算法

最短路

单源最短路

朴素dijkstra

时间复杂度O(n^2),适用于稠密图,所以用邻接矩阵存储

cpp 复制代码
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

const int N=510;

int n,m;
int g[N][N];
int dist[N];
bool st[N];

int dijkstra(){
    memset(dist,0x3f,sizeof(dist));
    dist[1] = 0;
    for(int i=0;i<n;i++){
        int t=-1;
        for(int j=1;j<=n;j++){
            if(!st[j] && (t==-1||dist[t]>dist[j]))
                t = j;
        }
        st[t]=true;

        for (int j = 1;j<=n;j++)
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }

    if(dist[n]==0x3f3f3f) return -1;
    return dist[n];
}

int main(){
    scanf("%d%d",&n,&m);
    memset(g,0x3f,sizeof(g));

    while(m--){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        g[a][b] = min(g[a][b], c);
    }

    int t=dijkstra();

    printf("%d\n", t);
}

堆优化dijkstra

时间复杂度m*logn

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

const int N = 100010;
typedef pair<int, int> PII;

int n, m;
vector<PII> edge[N];
int dist[N];
bool st[N];

int dijkstra()
{
    memset(dist, 0x3f, sizeof(dist));
    dist[1] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, 1});
    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();

        int ver = t.second;
        if (st[ver])
            continue;
        st[ver] = true;

        for (auto k : edge[ver])
        {
            int to = k.first;
            int w = k.second;
            if (dist[to] > dist[ver] + w)
            {
                dist[to] = dist[ver] + w;
                heap.push({dist[to], to});
            }
        }
    }

    if (dist[n] == 0x3f3f3f3f)
        return -1;
    return dist[n];
}

int main()
{
    scanf("%d%d", &n, &m);

    while (m--)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        edge[a].push_back({b, c});
    }

    int t = dijkstra();

    printf("%d\n", t);
}
/*
3 3
1 2 2
2 3 1
1 3 4
输出
3

*/

朴素bellman_ford

时间复杂度:O(nm)

k是经过多少条边,该算法可以求一点点经过多少条边到另外一点的最短路径

求1到n的最短路径,k为n-1

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;
const int N = 510, M = 10010;

int n,m,k;
int dist[N],backup[N];

struct Edge{
    int a, b, w;
}edges[M];

int bellman_ford(){
    memset(dist, 0x3f, sizeof(dist));
    dist[1] = 0;
    for(int i=0;i<k;i++){
        memcpy(backup,dist,sizeof(dist));
        for (int j = 0;j<m;j++){
            int a = edges[j].a, b = edges[j].b, w = edges[j].w;
            dist[b] = min(dist[b], backup[a] + w);
        }
    }
    if(dist[n]>0x3f3f3f3f/2)  return -1;  //防止∞+(-10) 更新∞
    return dist[n];
}

int main(){
    scanf("%d%d%d",&n,&m,&k);
    for (int i = 0; i < m;i++){
        int a,b,w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }
    int t=bellman_ford();
    printf("%d", t);
}
/*
3 3 1
1 2 1
2 3 1
1 3 3
输出
3
*/

优化spfa

限制:图中有负环

时间复杂度一般O(m),最坏O(nm)

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

const int N = 100010;
typedef pair<int, int> PII;

int n, m;
vector<PII> edge[N];
int dist[N];
bool st[N];

int spfa()
{
    memset(dist, 0x3f, sizeof(dist));
    dist[1] = 0;
    queue<int> q;
    q.push(1);
    st[1]=true;

    while(q.size()){
        int t=q.front();
        q.pop();
        st[t]=false;

        for (auto k:edge[t]){
            int to=k.first,w=k.second;
            if(dist[to] > dist[t] + w){
                dist[to] = dist[t] + w;
                if(!st[to]){
                    q.push(to);
                    st[to] = true;
                }
            }
        }
    }

    if (dist[n] == 0x3f3f3f3f)
        return -1;
    return dist[n];
}

int main()
{
    scanf("%d%d", &n, &m);

    while (m--)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        edge[a].push_back({b, c});
    }

    int t = spfa();

    printf("%d\n", t);
}
/*
3 3
1 2 2
2 3 1
1 3 4
输出
3

*/

spfa检测负环

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

const int N = 100010;
typedef pair<int, int> PII;

int n, m;
vector<PII> edge[N];
int dist[N],cnt[N];
bool st[N];

int spfa()
{
    queue<int> q;
    for (int i = 1;i<=n;i++){
        st[i]=true;
        q.push(i);
    }

        while (q.size())
        {
            int t = q.front();
            q.pop();
            st[t] = false;

            for (auto k : edge[t])
            {
                int to = k.first, w = k.second;
                if (dist[to] > dist[t] + w)
                {
                    dist[to] = dist[t] + w;
                    cnt[to] = cnt[t] + 1;

                    if(cnt[to] >= n)  return true;
                    if (!st[to])
                    {
                        q.push(to);
                        st[to] = true;
                    }
                }
            }
        }
        return false;
}

int main()
{
    scanf("%d%d", &n, &m);

    while (m--)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        edge[a].push_back({b, c});
    }

   if(spfa()) puts("yes");
   else puts("no");
}
/*
3 3
1 2 -1
2 3 4
3 1 -4
输出
yes

*/

多源最短路

Floyd

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

const int N = 210, INF = 1e9;

int n,m,Q;
int d[N][N];

void floyd(){
    for (int k = 1; k <= n;k++){
        for(int i=1;i<=n;i++){
            for (int j = 1;j<=n;j++){
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            }
        }
    }
}

int main(){
    scanf("%d%d%d",&n,&m,&Q);

    for (int i = 1; i <= n;i++){
        for (int j = 1;j<=n;j++){
            if(i==j)  d[i][j]=0;
            else d[i][j]=INF;
        }
    }
    while(m--){
        int a,b,w;
        scanf("%d%d%d",&a,&b,&w);
        d[a][b] = min(d[a][b], w);//重边
    }
    floyd();
    while(Q--){
        int a,b;
        scanf("%d%d",&a,&b);
        if(d[a][b]>INF/2) puts("impossible");
        else printf("%d\n", d[a][b]);
    }
    return 0;
}
/*
3 3 2
1 2 1
2 3 2
1 3 1
2 1
1 3
输出
impossible
1


*/
相关推荐
小雨下雨的雨3 小时前
井字棋AI机器人实现详解 - Minimax算法实战-鸿蒙PC Electron框架完成
前端·人工智能·算法·华为·electron·鸿蒙
xieliyu.5 小时前
Java算法精讲:双指针(三)
java·开发语言·算法
一条小锦吕*6 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化
如竟没有火炬7 小时前
最大矩阵——单调栈
数据结构·python·线性代数·算法·leetcode·矩阵
8Qi88 小时前
LeetCode 1143 & 718:最长公共子序列 / 最长重复子数组
算法·leetcode·职场和发展·动态规划
绿算技术8 小时前
万卡推理集群存储选型分析:从核心架构到应用视角
大数据·科技·算法·架构
想吃火锅10059 小时前
【leetcode】1.两数之和js版
javascript·算法·leetcode
net3m3310 小时前
一阶软件低通滤波器算法
人工智能·算法
水木流年追梦10 小时前
大模型入门-大模型优化方法12-YaRN 长文本外推技术
人工智能·分布式·算法·正则表达式·prompt