首页 > 编程语言 >最短路算法模版集合

最短路算法模版集合

时间:2024-02-29 11:01:04浏览次数:21  
标签:dist idx int 模版 短路 add st 算法 include

屏幕截图 2023-09-03 100818.png

例题https://www.luogu.com.cn/problem/P1339

朴素dijkstra (邻接表)

dijkstra 正确性来自于贪心 也就是st数组内的数(dist) 必须逐渐变大这样才能保证后面的数更新的时候,当前的第三边dist[t]都是最小值 [详见](https://www.acwing.com/solution/content/94237/) 

dist[x]表示 x到start 的最短距离

#include <iostream>
#include <cstring>
#include <algorithm>


using namespace std;

const int N = 2510, M = 6220 * 2;

int h[N], w[M], ne[M], e[M], idx;
int n, m, start, ened;
bool st[N];
int dist[N];

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

int dijkstra()
{
    dist[start] = 0;
    int k = n;
    while (k -- ) // 运行n - 1 次就行 n次一样不错就是多算一遍 可改成 --k
    {
        int t = -1;
        for (int i = 1; i <= n; i ++ )
            if (!st[i] && (t == -1 || dist[t] > dist[i]))
                t = i;
                
        st[t] = true;
        
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            dist[j] = min(dist[j], dist[t] + w[i]);
        }
    }
    
    return dist[ened];
}

int main()
{
    cin >> n >> m >> start >> ened;
    memset(h, -1, sizeof h);
    memset(dist, 0x3f, sizeof dist);
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
        add(b, a, c);
    }
    
    cout << dijkstra();
    
    return 0;
}

朴素dijkstra 邻接矩阵

#include <iostream>
#include <cstring>
#include <algorithm>


using namespace std;

const int N = 3510;

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


int dijkstra()
{
    dist[start] = 0;
    int k = n;
    
    while (k -- )
    {
        int t = -1;
        for (int i = 1; i <= n; i ++ )
            if (!st[i] && (t == -1 || dist[t] > dist[i]))
                t = i;
                
        st[t] = true;
        
        for (int i = 1; i <= n; i ++ )
            dist[i] = min(dist[i], dist[t] + g[t][i]);
    }
    
    return dist[ened];
}

int main()
{
    cin >> n >> m >> start >> ened;
    memset(dist, 0x3f, sizeof dist);
    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);
        g[b][a] = min(g[b][a], c);
    }
    
    cout << dijkstra();
    
    return 0;
}

堆优化dijkstra

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

using namespace std;

typedef pair<int, int> PII;

const int N = 2510, M = 6550 * 2;

int h[N], ne[M], e[M], w[M], idx;
int dist[N];
bool st[N];
int n, m, S, T;

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

int dijkstra()
{
    priority_queue<PII, vector<PII>, greater<PII>> q;
    q.push({0, S});
    dist[S] = 0;
    while (q.size())
    {
        auto t = q.top();
        q.pop();
        int ver = t.second, distance = t.first;
        if (st[ver]) continue;
        st[ver] = true;      // 标记已经用这个点更新过了 (此点目前最小)
        
        for (int i = h[ver]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > distance + w[i])
            {
                dist[j] = distance + w[i];
                q.push({dist[j], j});
            }
        }
    }
    return dist[T];
}

int main()
{
    cin >> n >> m >> S >> T;
    memset(h, -1, sizeof h);
    memset(dist, 0x3f, sizeof dist);
    while (m -- )
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
        add(b, a, c);
    }
    
    cout << dijkstra();
    return 0;
}

spfa

我更新过谁,我再拿被更新的这个更新别人。

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 2510, M = 6210 * 2;

int h[N], ne[M], e[M], idx, w[M];
int n, m, S, T;
int dist[N];
int q[N];
bool st[N];

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


int spfa()
{
    int tt = 1, hh = 0;
    q[hh] = S;
    dist[S] = 0;
    
    while (hh != tt)
    {
        int t = q[hh ++ ];
        if (hh == N) hh = 0;
        st[t] = false; // 退出队列后还有可能进来
        
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] > dist[t] + w[i])
            {
                dist[j] = dist[t] + w[i];
                if (!st[j]) // 保证队列中这个点只有一个
                {
                    q[tt ++ ] = j;
                    if (tt == N) tt = 0;
                    st[j] = true;
                }
            }
        }
    }
    
    return dist[T];
}
int main()
{
    cin >> n >> m >> S >> T;
    memset(h, -1, sizeof h);
    memset(dist, 0x3f, sizeof dist);
    while (m -- )
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
        add(b, a, c);
    }
    
    cout << spfa();
    
    return 0;
}

bellman_ford

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 2510, M = 6500 * 2;


int h[N], ne[M], e[M], w[M], idx;
int dist[N];
bool st[N];
int n, m, S, T;


void add(int a, int b, int c)
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}
int bellman_ford()
{
    int k = n;
    dist[S] = 0;
    while (k -- )
    {
        int backup[N];
        memcpy(backup, dist, sizeof dist); // 备份防止连续更新边 , 正常情况下没影响,限制边数时必须有
        for (int i = 1; i <= n; i ++ )
            for (int j = h[i]; j != -1; j = ne[j])
                dist[e[j]] = min(dist[e[j]], backup[i] + w[j]);
    }
    
    return dist[T];
}

int main()
{
    cin >> n >> m >> S >> T;
    memset(h, -1, sizeof h);
    memset(dist, 0x3f, sizeof dist);
    while (m -- )
    {
        int a, b, c;
        cin >> a >> b >> c;
        add(a, b, c);
        add(b, a, c);
    }
    
    cout << bellman_ford();
    
    return 0;
}

Floyd

原理是动态规划 时间复杂度O(n ^ 3)

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 2510;

int g[N][N];
int n, m, S, T;


int main()
{
    memset(g, 0x3f, sizeof g);
    scanf("%d%d%d%d", &n, &m, &S, &T);
    
    while (m -- )
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        g[a][b] = g[b][a] = min(c, g[a][b]);
    }
    for (int k = 1; k <= n; k ++ )
        for (int i = 1; i <= n; i ++ )
            for (int j = 1; j <= n; j ++ )
                if (i != j) g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
    
    printf("%d", g[S][T]);
    
    return 0;
}

标签:dist,idx,int,模版,短路,add,st,算法,include
From: https://www.cnblogs.com/blind5883/p/18042957

相关文章

  • 复习回顾-动态规划算法part6-377. 组合总和 Ⅳ
    注意点&感悟:跟卡尔的57题不一样,57爬楼梯,物品是m,背包是total总台阶数量,每次爬楼梯的m个foriinrange(1,m+1)选择是有限的377组合是,给的nums是物品,背包是target目标,每次这些物品都能选,选择是全部遍历一遍。foriinrange(len(nums)) 全部遍历题目链接:377.组合总和Ⅳ......
  • 【C++】相对于数组,在链表中添加和删除元素更容易,但排序速度更慢。这就引出了一种可能
    相对于数组,在链表中添加和删除元素更容易,但排序速度更慢。这就引出了一种可能性:相对于使用链表算法进行排序,将链表复制到数组中,对数组进行排序,再将排序后的结果复制到链表中的速度可能更快;但这也可能占用更多的内存。请使用如下方法检验上述假设。a.创建大型vector<int>对象vi0,并......
  • day44 动态规划part7 代码随想录算法训练营 70. 爬楼梯 (进阶)
    题目:爬楼梯(进阶)-在卡尔网我的感悟:昨天最后没怎么听懂的,今日回旋镖来了。理解难点:递推公式,和遍历顺序手写笔记:代码示例:total,m=map(int,input().split())#每次爬m个#dp[i]含义是爬到i有dp[i]种方法#是完全背包问题dp=[0]*(total+1)dp[0]=1fo......
  • 算法题目的时间复杂度和空间复杂度
    一、如何判断时间复杂度?  利用--大O记法:  1、只保留最高次项;  2、最高次项的系数默认是1;  3、常数次一律记为O(1)。例题1:voidtest1(){intn,m;cin>>n>>m;intsum=0;for(inti=0;i<n;i++){for(inti=0;i......
  • 代码随想录算法训练营第六天|242. 有效的字母异位词
    这个题目还是比较简单的,知道是查表的思路之后,很快就写出来了:classSolution:defisAnagram(self,s:str,t:str)->bool:iflen(s)!=len(t):returnFalsealphabet=[]dict_s={}dict_t={}foriinran......
  • 代码随想录算法训练营day08 | leetcode 344. 反转字符串、541. 反转字符串 II、54. 替
    目录题目链接:344.反转字符串-简单题目链接:541.反转字符串II-简单题目链接:[54.替换数字](题目页面(kamacoder.com))题目链接:151.反转字符串中的单词-中等题目链接:[55.右旋字符串](题目页面(kamacoder.com))题目链接:344.反转字符串-简单题目描述:编写一个函数,其作用是将......
  • 数据结构与算法
    绪论数据结构的基本概念数据:是信息的载体,分整数型与非整数型数据数据项:构成数据元素的最小不可分割单位,如学生的成绩数据元素:数据的基本单位,作为一个整体存储,如每个学生的信息数据类型:具有相同性质的计算机数据的集合,以及在这个集合上的一系列操作,比如in......
  • 2024牛客寒假算法基础集训营6 题解 ( A,B,C,D,E,I)
    2024牛客寒假算法基础集训营6题解(A,B,C,D,E,I)A 宇宙的终结题意找到\([l,r]\)区间中有多少数恰好等于三个不同素数的乘积思路数据范围很小,可以考虑暴力,遍历\([l,r]\)区间内每个数,拿每个小于当前数的素数一直往下除,判断是否存在能被恰好3个素数整除的情况代码/********......
  • (8)宽带信号的空间谱估计算法
    空间谱估计理论与算法(8)宽带信号的空间谱估计1引言目前,对宽带信号处理算法的研究主要分为两类:1基于不相干信号的处理方法(ISM)。这类算法处理的主要思想是将宽带数据分解到不重叠频带上的窄带数据,然后对每个频带进行窄带信号子空间处理,从而获得初始角度的估计;再通过对这些初始估......
  • 加密算法(三级等保)
    常见的加密算法对称加密算法DES、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6和AES非对称加密算法RSA、ECC(移动设备用)、Diffie-Hellman、ElGamal、DSA(数字签名用)Hash算法MD2、MD4、MD5、HAVAL、SHA、SHA-1、HMAC、HMAC-MD5、HMAC-SHA1块加密概念块加密,英文BlockCyper......