最短路问题的五种算法

图论 ——五种最短路算法 文章目录 前言 一、最短路是什么? 二、朴素Dijkstra算法 三、堆优化版Dijkstra算法 四、Bellman-Ford算法 五、Spfa算法 六、Floyd算法 总结 前言 本篇文章讲的是图论里的最短路问题,如果你还没有图论的基础知识,可以看看我之前的文章: DFS(深度优先算法)BFS(广度优先算法)邻接表和邻接矩阵、树的遍历 (DFS和BFS) 这些都是关于图论的基本知识。 一、最短路是什么? 最短路径: 从某个点A(位置)到另一个点B(位置)的最.. 阅读详情


基础算法合集:
https://blog.youkuaiyun.com/GD_ONE/article/details/104061907

摘要

本文主要介绍关于图的最短路的五种常用算法和其应用。朴素Dijkstra, 堆优化Dijkstra,Bellman-Ford,SPFA, Floyd。这几种算法有各自的优势和劣势,适用于不同的场景。
另:本篇文章篇幅较长,但难度不大, 建议学习算法的同时,自己手动画图,并模拟算法流程,将会一目了然,所见即所得!


单源最短路: 一个点到其他点的最短路。

无负边权时适用算法(所有边长都为正数):

  • 稠密图: 朴素Dijkstra

  • 稀疏图: 堆优化Dijkstra, SPFA

有负边权时适用算法:

  • SPFA
  • Bellman-Ford

求有边数限制的单源最短路:

  • Bellman-Ford

多源汇最短路: 任意两点间的最短路。

  • Floyd

图的存储方式

存储稠密图时,使用邻接矩阵。
存储稀疏图时,使用邻接表。
稠密图是指边数远大于点数,稀疏图是边数和点数差不多相等。
以n表示点数, m表示边数,
一般来说题目数据是n < 100, m < 10000 的图是稠密图, 是n<10000, m<10000的图是稀疏图。


朴素Dijkstra

算法思想:

朴素DijKstra的思想是通过一个距离起点A最近的点B,缩短起点A通过点B到达其他点的距离,因为只有通过距离起点最近的点,才有可能缩短起点到达其他点的距离。
所以一共分两步:
第一步:找到距离起点最近的点。
第二步:通过该点缩短起点到达其他点的距离。

比如:

在这里插入图片描述
对于AB和AC, AB为3, AC 为6,AB是A到其他点的最短距离,如果AC有可能更小的话,那么一定是经过B。原本A到C是6, 但经过B, ABC的距离是4.所以AC的最短距离是4.

所以怎么实现呢?

  1. 我们设置一个dis数组,来表示其他点到起点的最短距离。起点到起点的距离是0,所以dis[1] = 0, 其他点现在到起点的距离全部设为正无穷。
  2. 然后,我们要找到一个距离起点最近点。用一个循环遍历一下。
int t = -1; // 表示还没有处理过的距离起点最近的点。
// 找出距离起点最近的点。
for(int j = 1; j <= n; j++){
	if(st[j]==0 && (t==-1 || st[t] > st[j])
		t = j;
}

最终t就是我们找到的还没有处理过的距离起点最近的点。
处理的意思就是已经确定该点的最短路径。
然后通过t这个点,去缩短起点到达其他点的距离。

for(int j = 1; j <= n; j++){
	dis[j] = min(dis[j], dis[t] + w[t][j])
}

核心代码:

public static int Dijkstra(){
       Arrays.fill(dis, 0x3f3f3f3f);
        dis[1] = 0;
        for(int i = 0; i < n; i++){ // 循环n次, 每次找出一个离起点最近的点。
            int t = -1;
            for(int j = 1; j <= n; j++){
                if(S[j] == 0 && (t == -1 || dis[t] > dis[j])){ // 找到一个距离最短的加入S集合。
                    t = j;
                }
            }
            
            S[t] = 1;  // 然后通过这个点来缩短原点到达其他点的距离。
            for(int j = 2; j <= n; j++){
                dis[j] = Math.min(dis[j], dis[t] + w[t][j]);
            }
        }    
        
        if(dis[n] != 0x3f3f3f3f) return dis[n];
        else return -1;
    }    

例题:Dijkstra求最短路
在这里插入图片描述
JAVA代码:

import java.io.*;
import java.util.*;

public class 朴素Dijkstra{
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    static final int N = 505;
    static int w[][] = new int[N][N];
    static int dis[] = new int[N]; // 每个点距离原点的距离。
    static int S[] = new int[N]; // 最短路集合
    static int n,m;
    
    public static int Int(String s){
        return Integer.parseInt(s);
    }
    
    public static int Dijkstra(){
       Arrays.fill(dis, 0x3f3f3f3f);
        dis[1] = 0;
        for(int i = 0; i < n; i++){ // 循环n次, 每次找出一个离起点最近的点。
            int t = -1;
            for(int j = 1; j <= n; j++){
                if(S[j] == 0 && (t == -1 || dis[t] > dis[j])){ // 找到一个距离最短的加入S集合。
                    t = j;
                }
            }
            
            S[t] = 1;  // 然后通过这个点来缩短原点到达其他点的距离。
            for(int j = 2; j <= n; j++){
                dis[j] = Math.min(dis[j], dis[t] + w[t][j]);
            }
        }    
        
        if(dis[n] != 0x3f3f3f3f) return dis[n];
        else return -1;
    }    
    
    public static void main(String[] args) throws Exception{
        String s[] = in.readLine().split(" ");
        n = Integer.parseInt(s[0]);
        m = Integer.parseInt(s[1]);
        
        for(int i = 0; i < n; i++)
            Arrays.fill(w[i], 0x3f3f3f3f);
            
        for(int i = 0; i < m; i++){
            String s1[] = in.readLine().split(" ");
            int a, b, c;
            a = Int(s1[0]);
            b = Int(s1[1]);
            c = Int(s1[2]);
            w[a][b] = Math.min(w[a][b],c);
        }
        
        out.write(Dijkstra()+"\n");
        out.flush();
    }
}

堆优化Dijkstra

算法思想:

堆优化其实就是使用优先队列对图BFS一遍,在搜索的同时更新点的距离。
朴素算法需要遍历所有点找出距离最近的点,使用优先队列使这一步的时间复杂度从n变为了logn。
对于走迷宫问题,我们很容易可以使用BFS找出最短路,因为每个点与点之间的距离是一样的,但是当边权不同时,显然我们必须先遍历近距离的点,这时我们就可以使用优先队列来达到这一目的。

关键代码:

    public static int Dijkstra(){
    	Arrays.fill(dis, INF); // 初始化dis数组为正无穷
    	q.add(new Pair(0, 1)); // 将起点当做一个距离起点最近的点加入优先队列。
        dis[1] = 0; // 起点到起点的距离是0.
        while(!q.isEmpty()){  // 广度优先搜索 + 堆优化。
        	Pair t = q.poll();
        	if(S[t.a] == 1) continue;
        	S[t.a] = 1;
        	
        	for(int i = h[t.a]; i != 0; i = ne[i]){  //搜索当前点的所有邻接点。
        		if(dis[e[i]] > t.w + w[i]){ // 更新距离
        			dis[e[i]] = t.w + w[i];
        			q.add(new Pair(dis[e[i]], e[i]));
        		}
        	}
        }
        if(dis[n] != INF) return dis[n]; // 可以到达n号点
        else return -1; 
    }
}

还是上个题目使用堆优化来做:

import java.io.*;
import java.util.*;

class Pair{
    int w;
    int x;
    Pair(int a, int b){
        w = a;
        x = b;
    }
}

public class 堆优化Dijkstra{
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    static BufferedWriter out = new BufferedWriter(new OutputStreamWriter(System.out));
    
    static final int N = 100010, INF = 0x3f3f3f3f;
    static int n, m;
    static int[] w = new int[N], dis = new int[N];
    static int[] e = new int[N], ne = new int[N], h = new int[N], S = new int[N];
    static int idx = 1;
    
    static PriorityQueue<Pair> q = new PriorityQueue<>(11, new Comparator<Pair>(){
		public int compare(Pair a, Pair b) {  
        	return a.w - b.w; 
		}
    });//自定义类需要重写比较器
    
    public static void add(int a, int b, int c){
    	e[idx] = b;
    	w[idx] = c;
    	ne[idx] = h[a];
    	h[a] = idx++;
    }
    
    public static int Int(String s) {return Integer.parseInt(s);}
    
    public static int Dijkstra(){
    	Arrays.fill(dis, INF);
    	q.add(new Pair(0, 1));
        dis[1] = 0;
        while(!q.isEmpty()){  // 广度优先搜索 + 堆优化。
        	Pair t = q.poll();
        	if(S[t.x] == 1) continue;
        	S[t.x] = 1;
        	
        	for(int i = h[t.x]; i != 0; i = ne[i]){  // h[i]中存的是第i条个点指向的点。
        		if(dis[e[i]] > t.w + w[i]){
        			dis[e[i]] = t.w + w[i];
        			q.add(new Pair(dis[e[i]], e[i]));
        		}
        	}
        	
        }
        if(dis[n] != INF) return dis[n];
        else return -1;
    }
    
    public static void main(String[] args) throws Exception{
    	String s[] = in.readLine().split(" ");
    	n = Int(s[0]);
    	m = Int(s[1]);
    	for(int i = 0; i < m; i++){
    		String s1[] = in.readLine().split(" ");
    		add(Int(s1[0]), Int(s1[1]), Int(s1[2]));
    	}
    	out.write(Dijkstra()+"\n");
        out.flush();
    }
}

Bellman-Ford

算法思想:

Dijkstra算法是以一个距离起点最近的点为基准点,缩减其邻接点到起点的距离,是贪心思想。
而Bellman-Ford算法是先将每个点到达起点的距离设为正无穷,然后直接暴力枚举所有边,如果一个点的距离可以被更新,就更新该点的距离。枚举一次至少可以得到一个点到达起点的距离,直接无脑枚举n次,就可以得到所有点到起点的最短距离。
核心代码:

   void BellMan_Ford(){
        Arrays.fill(dist, 0x3f3f3f3f); // 初始化dis数组为正无穷
        dist[1] = 0;
        
        for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
            	int a = edge[j].a, b = edge[j].b, w = edge[j].w;
                if(dist[b] > dist[a] + t.w) //如果从a->b的距离加上dis[a] > dis[b] 则更新dis[b
                    dist[b] = dist[a] + t.w;
            }
        }
    }

可以看到最核心的就是两个for循环。手动画画图还是很好理解的。

求总路径条数不多于K条的最短路径

如果我们对Bellman-Ford算法进行一些限制,它就可以用来求有边数限制的最短路问题。

比如要求1到n的不多于1条边的最短路径,如果1不能直接到n,那么最短路径的边数一定是大于1的,此时就无解。
画个图:

在这里插入图片描述
用Bellman-Ford算法对求上图中1号点到3号点的最短路:

  for(int i = 0; i < n; i++){
            for(int j = 0; j < m; j++){
                int a = edge[j].a, b = edge[j].b, w = edge[j].w;
                if(dist[b] > dist[a] + w) 
                    dist[b] = dist[a] + w;
            }
        }

第一次枚举所有边的过程中,先得到2号点到1号点的距离,然后得到3号点到一号点的距离。虽然外层循环只进行了一次,却得到了边数大于2的路径长度,这与我们想要得到边数不多于k条边的目的是冲突的,如果我们限制每次遍历所有边时最多只能修改某个点的直接后继,而不能修改一个点后继的后继,那么遍历所有边k次后,得到的结果就是边数不多于k条的最短路。

看图:

第一次遍历所有边:得到2,3的距离

在这里插入图片描述

第二次遍历所有边:得到4,6的距离
在这里插入图片描述
第三次遍历所有边:得到5的距离
在这里插入图片描述
怎么实现呢,很简单,对每个点的距离进行更新时,用上一次更新后的结果去更新就行了。需要加个辅助数组去存储上一次更新后点的位置。

 void BellmanFord(){
        Arrays.fill(dist, 0x3f3f3f3f);
        dist[1] = 0;
        int[] last = new int[N];
        for(int i = 0; i < k; i++){
            System.arraycopy(dist, 0, last, 0, m); //将dist赋值给last
            for(int j = 0; j < m; j++){
                Pair t = p[j];
                if(dist[t.b] > last[t.a] + t.x)
                    dist[t.b] = last[t.a] + t.x;
            }
        }
    }

例题:有边数限制的最短路

Bellman-Ford算法时间复杂度很高,有人对其进行了优化,SPFA就是用队列优化版Bellman-Ford算法。

SPFA

我们知道Bellman-Ford是每次遍历所有边,如果一个点被搜索到了,就更新距离。 但是每一次遍历时是有一些点是无论如何都不会被搜索到的。这跟边的读入顺序有关。

比如读入:
2 3 1
1 2 1

代表2到3的距离是1, 1到2的距离是1

我们先存储的是2到3的边,所以就会先遍历2->3, 此时2和3到1的距离都是正无穷,所以3的距离不会被更新。

如果读入顺序是
1 2 1
2 3 1
我们一次循环就可以得到3号点的值。

算法思想:

我们在一次循环中做了很多不必要的操作,如果我们可以只更新那些前驱结点被更新过的点,就可以大大提升效率。因为只有前驱结点到达起点的距离减小了,它的后继结点到达起点的距离才能减小。

所以我们用宽搜的思想,每次将被更新过的点入队,然后遍历队列中每个点的后继结点,重复更新操作和入队操作。

虽然SPFA和堆优化版的Dijkstra很相似,但是两种搜索策略却是不同的。细细品。

核心代码:

  public static void SPFA(){
    	Arrays.fill(dis, 0x3f3f3f3f);
    	dis[1] = 0;
        q.add(1);
        while(!q.isEmpty()){
            int t = q.poll();
            s[t] = 0; //出对后标记为0,因为可能存在负权边,所以一个点可能会被更新多次,
            //所以一个点只要被更新过就能入队,次数不限
            
            for(int i = h[t]; i != 0; i = ne[i]){
                int j = e[i];
                if(dis[j] > dis[t] + w[i]){
                    dis[j] = dis[t] + w[i];
                    if(s[j] == 0){// 如果该点当前不在队中,就入队,避免重复操作。
                        q.add(j);
                        s[j] = 1; //标记已在队中
                    }
                }
            }
        }
    }
    

堆优化Dijkstra和SPFA的区别和优缺点

两者虽然很像,而且思想上也有一些相似,但终究是两种不同的算法,

Dijkstra是以一个距离起点最近的点为基础去修改其邻接点,堆优化后,要对一个点的所有边进行堆排序,然后每次从最近的点开始遍历。但是,如果存在负边权,就不能保证当前点到起点的距离是最短的。比如
1->2 = 1 , 1->3 = 2, 3->2 = -2,
那么1->2的最短距离其实是0,而不是1。这就是为什么DijkStra不能处理负权边。

SPFA则不对边排序, 而是一股脑的遍历一个被更新过的点的所有边。因为省去了堆排序这一步骤,大部分时候SPFA是要快于堆优化的Dijkstra的。

但是!! SPFA可能会被网格图等特殊构造的图卡成o(nm)的时间复杂度,所以一般还是要用堆优化Dijkstra。但是!!如果有负边权,那么就只能用SPFA了。


用SPFA判断负环

负环:
在这里插入图片描述
对于上图来说,1->2-> 3->1 就是一个负环,根据SPFA算法的性质,会将距离被更新过的点入队,因为存在负环,所以只要每次经过一次负环,所有点到起点的距离就会被不断减小,即SPFA就会陷入死循环,其他点到起点的距离最终会变为负无穷。
如果我们能找到一个条件,确定循环多少次后,就可以判断存在负环, 我们就可以强制结束SPFA,从而判断是否存在图中负环。
这个条件就是:

只要不存在负环,起点到达任意点所经过的边数一定小于n,反之一定大于等于n因为只有n个点,不经过环的话最多经过n-1条边,只有在存在负环的情况下,SPFA才会经过负环,经过负环后,到达其他点边数就会大于等于n,

代码:

public static int SPFA(){
    //因为目的是判断有无负环,所以先要将所有点都当做起点加入队列,因为一个图可能分成不连通的几部分,而负环存在于其中某一个连通块。
	for(int i = 1; i <= n; i++){
    	    q.add(i);
    	}
 
        while(!q.isEmpty()){// 这里不需要对dis数组初始化,因为存在负环的话距离会小于0.
            int t = q.poll();
            s[t] = 0;
            
            for(int i = h[t]; i != 0; i = ne[i]){
                int j = e[i];
                if(dis[j] > dis[t] + w[i]){
                    dis[j] = dis[t] + w[i];
                    cnt[j] = cnt[t] + 1;  // 将当前点到起点的距离+1
                    if(cnt[j] >= n){
                        return 1;
                    }
                    if(s[j] == 0){
                        q.add(j);
                        s[j] = 1;
                    }
                }
            }
        }
        return 0;
    }

Floyd

先说说Floyd的优点

Floyd算法用来求任意两点间的最短路,我们当然可以用上面说过的算法如SPFA,对一个图的每个点都当成起点,求其最短路,但如果是稠密图,其时间复杂度也会很高,而Floyd算法实现十分简单,还能再O(n^3)内完成

Floyd是本次所有算法中最短的了!
对于算法来说,代码长的不一定难懂,但短的一定不会很难懂。

算法思想:

对于朴素Dijkstra算法来说,起点通过距离它最近的点去缩短其到达其他点的距离,Floyd算法本质上也是这样的思想。
第一步 :通过一个点,遍历所有点对,更新距离。
第二步:通过n个点,遍历所有点对n次,更新距离。

核心代码:

void floyd()
{
    for (int k = 1; k <= n; k ++ ) //通过n个点
        for (int i = 1; i <= n; i ++ ) // 遍历所有点对。
            for (int j = 1; j <= n; j ++ )
                arr[i][j] = min(arr[i][j], arr[i][k] + arr[k][j]);
}

第一层循环就是枚举n个点, 内部两层循环来枚举所有点对。

总结

  1. 一定要画图。
  2. 一定要刷题。
  3. 写题的时候一定要注意是不是无向图, 无向图的话建边时要建一来一去两条,如果用邻接表存,数组一定要开足够大,至少是边数的两倍。
  4. 对于邻接矩阵,要判断重边。邻接表则不需要判断重边。

最短路题单:
https://vjudge.net/contest/66569
POJ 2387 Til the Cows Come Home
POJ 2253 Frogger
POJ 1797 Heavy Transportation
POJ 3268 Silver Cow Party
POJ 1860 Currency Exchange
POJ 3259 Wormholes
POJ 1502 MPI Maelstrom
POJ 3660 Cow Contest
POJ 2240 Arbitrage
POJ 1511 Invitation Cards
POJ 3159 Candies
POJ 2502 Subway
POJ 1062 昂贵的聘礼
POJ 1847 Tram
LightOJ 1074 Extended Traffic
HDU 4725 The Shortest Path in Nya Graph
HDU 3416 Marriage Match IV
HDU 4370 0 or 1
POJ 3169 Layout

以上题单源自Kuangbin专题

最短路问题(五个算法模板) 题目给定一个有向图,图中有 𝑛n 个点和 𝑚m 条边。图中可能存在重边和自环,所有边权均为正值。请你求出从 1 号点到 𝑛n 号点的最短距离。如果无法从 1 号点走到 𝑛n 号点,则输出 -1。 阅读详情

相关推荐

算法系列——四种最短路算法:Floyd,Dijkstra,Bellman-Ford,SPFA

写在前面: 好久没有更新博客了,距离上一次更新已经过去了十一个月了,一是因为课业繁重,二是因为这一年中接了不少项目。其实早就想写写算法和数据结构相关的文章了,之前在Coders群里也说过17年要多写写算法和数据结构,奈何计划赶不上变化,实在是没有工夫写。现在到了18年了,最近刚放寒假,数据科学导论实验今天交上了最后一个,总算是有些闲工夫了,准备写些东西却又不知道应该写什么,算法那么多,从哪个写起呢?思来想去,想到了最短路径算法,因为博主今年开了计算机网络课程,在计算机网络中,有一个很重要的东西就是路由,即

ITString的博客 892

最短路算法总结(超详细~)

文章目录最短路算法框架朴素Dijkstra算法堆优化版Dijkstra算法 最短路算法框架 最短路有五种算法,分别适用不同的情况。 单源最短路: 求一个点到其他点的最短路 多源最短路: 求任意两个点的最短路 稠密图用邻接矩阵存,稀疏图用邻接表存储。 稠密图: m 和 n2 一个级别 稀疏图: m 和 n 一个级别 朴素Dijkstra算法 Dijkstra算法是通过 n 次循环来确定 n 个点...

wmy0217_的博客 4万+

浅谈五种最短路算法(c++)

最短路问题,说人话就是给定一个图,求两个点之间所有走法中,边权和最短的路的值。总的来说,最短路算法分为5个不同的种类。 floyd 概述 floyed算法是多元最短路的算法(说人话:随便两个点我都能求),主要思想就是只要算的多就一定能做出来。 思路 每次找到一个点k,在遍历所有点,找到一对i,j,d[i][j]=min(d[i][j],d[i][k]+d[k][j]); 例题 题目描述 样例输入 时间复杂度分析 由循环易知,时间复杂度是O(n^3)。(200以上的数据就不要用了)

2301_79587247的博客 2104

最短路的四种算法

求最短路一般有四种方法: 1.dijkstra 邻接矩阵。 时间复杂度O(N^2) 2.dijkstra 邻接表+优先级队列优化。

tzw513的博客 1675

从Simulink仿真到DSP28335真机部署:PID闭环控制快速移植指南

本文详细介绍了如何将Simulink中的PID闭环控制算法快速移植到DSP28335嵌入式平台。通过模型与代码映射、浮点与定点数选择、定时器中断配置、物理输出实现以及调试技巧五个关键步骤,帮助工程师高效完成从仿真到真机部署的全过程,特别适合需要实现精确控制的嵌入式开发者。

weixin_42521843的博客 363

Benchmark系列——UnixBench测试项深度解析与性能优化指南

本文深度解析UnixBench基准测试套件的各项测试原理,包括Dhrystone、Whetstone、系统调用、进程管理、IPC及文件I/O等核心测试项。通过详细的测试项分析,指导用户解读测试报告,并提供针对性的内核参数调整、编译优化及系统配置实战指南,帮助用户精准定位并优化系统性能瓶颈。

weixin_29230901的博客 276

【图论】最短路问题大合集,五种算法刷爆最短路问题。

思路:迭代n次,每次找到距离离起点最近的点,起点置为0,并且用距离最近的点更新其他点。题目:给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环,所有边权均为正值。请你求出 1 号点到 n 号点的最短距离,如果无法从 1 号点走到 n 号点,则输出 −1。输入格式:第一行包含整数 n 和 m。接下来 m 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。输出格式:输出一个整数,表示 1 号点到 n 号点的最短距离。

m0_70875482的博客 1139

Abaqus 2023 保姆级安装避坑指南:从环境变量到许可证配置,一次搞定

本文提供Abaqus 2023的详细安装指南,涵盖环境变量设置、许可证配置等关键步骤,帮助用户避开常见安装陷阱。通过系统环境检查、目录结构规划、许可证服务器安装及Java环境配置等实用技巧,确保顺利完成安装并优化软件性能。

weixin_42524276的博客 426

最短路问题

文章目录最短路问题一.朴素dijkstra算法二.堆优化版dijkstra 算法三.Bellman-Ford算法四.spfa 算法五.floyd算法六.一些题目题1:信使题2:香甜的黄油题3:最小花费七.附录(四种解法模板,转载自[AcWing](https://www.acwing.com/blog/content/405/))1.朴素dijkstra算法2.堆优化版dijkstra3.Bellman-Ford算法4.spfa 算法5.floyd算法 最短路问题 序:最短路问题:求图中某个点到另一个点所

小皮皮LL的博客 865

极化码自适应CA-SCL译码(极化码译码)

我们知道最初极化码提出来是运用SC译码,但短码和中等长度其译码性(误码率)能不如LDPC码码,,为了提升有限长度极化码的译码性能,我们主要从译码器的性能和极化码的纠错性能来考虑。 SCL:在增加复杂度的情况下,大幅度增加极化码纠错性能,在高信噪比下,与最优ML性能相同(L=32) CA-SCL:改善最小汉明距离(最小汉明距离增大),增加其纠错性能。把CRC和极化码极联。 自适应CA-SCL:CA-SCL译码虽然提升几乎没的纠错性能,但是导致复杂度大幅度增加,为了降低其复杂度,让L自适应,从而降低其复杂度

m0_52610504的博客 3294

Mplus—交叉滞后面板模型(Cross-Lagged Panel Model, CLPM)

本文介绍交叉滞后模型相关知识,以及显变量模型与潜变量模型在Mplus中的语法。

m0_54401011的博客 1万+

gpt-ai-assistant 配置管理避坑指南:4 个关键参数与 5 个高频翻车问题

你带着 `NODE_ENV=development` 启动,在 LINE 里问什么,gpt-ai-assistant 都只回「OK!」。先别怀疑 API key 或模型坏了——这是它配置系统故意干的:非 production 环境会直接返回固定 mock。这也是 gpt-ai-assistant 配置管理里最典型的翻车现场:配置值不是没加载,而是被环境规则悄悄换掉了。不列参数清单了,下面跟着几个真

gitblog_00651的博客 291

牛耕式全覆盖算法-matlab代码

牛耕式路径全覆盖算法,也称为牛耕算法或者蚂蚁算法,是一种用于解决路径规划问题的启发式算法。这个算法的灵感来自于牛在耕田时的行为。在这个算法中,假设有一块田地需要耕作,牛从田地的某个角落开始行走,走过的路径会被标记。牛会优先选择尚未经过的路径,当所有的路径都走过后,算法停止。在路径规划问题中,田地可以看作是一个由节点和边构成的图。每个节点代表一个位置,每条边代表两个节点之间的连接。路径全覆盖问题是找出一组路径,使得每个节点都被至少一条路径经过。牛耕式路径全覆盖算法的基本思想是以启发式的方式逐步构建路径。

m0_69611489的博客 1690

[图+最短路+模板] 五大最短路常用模板

文章目录0. 前言1. 朴素 Dijkstra 算法求最短路2. 堆优化 Dijkstra 算法求最短路3. Bellman-Ford 算法求最短路 0. 前言 图论中最短路问题一般有两大类,然后在这两大类的基础上再细分为几个子项,下面简单梳理下知识点,总共 5 大最短路算法: 单源最短路: 源点,就是起点的意思。汇点,就是终点的意思。从一个点到所有点的最短距离。例,求解 1 号点到 n 号点的最短路,那么我们可以求解出从 1 号点到 n - 1 号点的所有最短路,那么显然,从 1 号点到 n 号点的最短

Y-puyu 的博客 1108

JavaScript教程-字符集,Unicode转义序列,标识符,数据类型,数字,未定义值,浮点数,字符串,引用数据类型,类型检测,类型转换,运算符,关系运算符,

前端学习

VAN 213

用Python爬取大连商品交易所期货实时行情:从入门到实战

python复制编辑# utils.py"豆粕": "M0","铁矿石": "I0","聚乙烯": "L0","玉米": "C0","聚丙烯": "PP0","棕榈油": "P0"本项目展示了:✅ 如何从新浪财经 API获取主力合约实时数据✅ 使用Python异步爬虫技术) 提升效率✅ 利用pandas和matplotlib进行结构化分析与可视化✅ 具备良好的扩展性,可对接金融、农业、能源等数据需求场景✅ 可作为期货量化策略数据源✅ 可嵌入自动化报告系统。

2201_76125261的博客 1247

【图论最短路算法总结】

图论_最短路算法: Floyd Dijkstra Bellman-Ford SPFA Johnson 全源最短路 1. Floyd: ·时间复杂度:O(n3) ·使用范围:无负权回路的稠密图,应用于数据较小的题目,可以求出任意两点之间的最短路 memset(d,0x3f,sizeof d);//初始化 for(int k=1; k<=n; k++){//枚举中间点 for(int i=1; i<=n; i++){ if(i!=k) for(int

lovermaker的博客 283

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

三种最短路基本知识

三种最短路1:朴素dijkstra算法(1)算法原理(2)时间复杂度及适用情况(3)代码2:用堆栈优化的dijkstra算法(1)算法原理(2)时间复杂度及适用情况(3)代码3:Bellman-Ford算法(1)算法原理(2)时间复杂度及适用情况(3)代码4:SPFA算法(用队列优化的Bell)(1)算法原理(2)时间复杂度及适用情况(3)代码5:spfa证明是否存在负环(1)算法原理(2)时间复杂度及适用情况(3)代码6:Floyd算法(1)算法原理(2)时间复杂度及适用情况(3)代码 1:朴素dijks

qq_54783066的博客 260

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

深搜之迷宫类

常见的迷宫类搜索可以分为以下5种类型 1. 找一组可行解(判断是否可行) 2. 所有可行解 3. 最优解(通常见最少步数) 4. 计算连通块数目 5. 求最大连通块

JohnnyLin 2033

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

图论升级*

A. Codeforces 296D 重题 Code #include<bits/stdc++.h> using namespace std; const int maxn=503,INF=1050000000; int g[maxn][maxn],n,a[maxn]; long long ans[maxn]; long long floyd(int I){ long long...

weixin_30632089的博客 82

牛客周赛 Round 39vp(A--F)

我们对于 p 个编号为0,1,⋯,p−1 的点,进行连边:编号为 i 的点向编号为 (i+a1)%p....(i+an)%p​ 的点连边。首先参考牛客B站视频的DP过了95%(数据有点水),原因在于它有一点不同于完全背包,就是%p后可能变得跟小,因此我们还要回过头考虑前面的,因此在内部还要加一层循环。我们考虑预处理出su[i]表示走i步所要的min次数(注意这里的min只考虑了同一个物品,比如选1个还是选2个,不是选一个1再选一个2)带了懒标记的线段树,维护A,B以及A和B共有的1的即可。

cocoack的博客 415

DAIN视频插帧指南:3步本地跑出中间帧,x4慢动作一步到位

DAIN是一个深度感知的视频插帧模型,帮你在两帧相邻画面之间补出平滑的中间帧,也能生成x4、x8、x10的慢动作视频。按这篇的步骤做一遍,就能在本地编译好CUDA扩展、加载官方预训练权重,三步拿到第一批插帧结果。 ## DAIN解决什么问题:用深度消除中间帧的鬼影 视频帧率不够时,快速运动会产生鬼影和撕裂。DAIN显式检测画面里的遮挡(哪个物体被另一个物体挡住),利用深度线索判断谁离镜头近,在

gitblog_01182的博客 219

CSP 2016-9

1.最大波动 o(n) 模拟即可 #include<iostream> #include<cmath> #include<algorithm> using namespace std; #define N 1000 int a[N]; int main(){ int n; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; int ans=0; for(int i=

Mj200644的博客 162

ZOJ 1649 Rescue (BFS)

题目大意:在一个矩阵里,有五种字符,一种是起点,一种是终点,一种代表墙不能走的,一种代表警卫需要花时间杀警卫的,最后一种代表路,每走一个格要花一个单位时间,杀一个警卫要花一个单位时间。求从起点到终点,花得最短时间! 分析:最短路径,其实很简单的,bfs搜索,然后判断一下是不是墙,是不是警卫和路,分别处理;在用一个数组d来记录每个点到起点的最短路径,同时也是用来标记已经遍历过的状态。 代码:

AClion的专栏 1074

LeetCode 743 Network Delay Time 全解法剖析:从 Dijkstra 到 SPFA 的最短路径实战指南

本篇指南以本仓库中 [network-delay-time 题解](https://link.gitcode.com/i/ce8f87a28a0325bf81a79bd2c0d099a4) 及其 [解题提示](https://link.gitcode.com/i/44cc5b0961dd30e6a1cdff3936eede03) 为主体,系统讲解 LeetCode 743 "Network Del

gitblog_06864的博客 154
上一篇: 深度优先搜索(DFS)和广度优先搜索(BFS)
下一篇: 二分法
Androids_lost_Sheep
博客等级 码龄8年 1022粉丝 86原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值