【算法设计】最短路理解+费用流入门学习初步小结

图论专题小结:最小费用最大流算法 一,给定流量F,求最小费用 题意:网络中有两台计算机s,t。现在每秒钟要从s到t传输大小为F的数据到t。该网络中一共有N台计算机,其中有一些靠单向电缆相连接每条电缆用(from,to,cap,cost)表示从from发送给to,最大容量是cap,单位传输费用是cost。问传输数据最小的花费是多少? 解决最小费用流的一般思路是:每次都沿着最短路进行增广,增广一次之后累加本次增广的总费用, 阅读详情

费用流入门学习初步小结

0 前言

​ 5月份开始任务宛如洪水,写了两篇周小结感觉毫无干货,于是直接熄火备战期中考,然后是期末考、project等。现在可以慢慢腾出一定的时间,稍微总结一下学期的内容。

​ 《算法分析与设计》课程让我重温了以前的一些知识点,学的一塌糊涂( ̄▽ ̄)"。在期末学习费用流时,因为用到了SPFA,所以想一起把最短路的几个点也梳理一下。大二的时候想梳理一遍最短路,那时用word码字,效率低,写了一点懒得写了( ̄▽ ̄)"。趁这个机会,打算按照【最短路总结】、【网络流和费用流】的思维顺序,进行丢丢个人理解的梳理。

1 最短路总结

​ 这部分内容,在草稿箱里从17年8月躺倒现在,着实离谱。实在是太懒了…( ̄▽ ̄)"

​ 学习最短路算法,一个很基础的概念是”松弛“。然后呢,去理解 Dijkstra、Floyd、Bellman-ford算法的关键思想,然后再了解两个算法优化版本”优先队列优化的Dijkstra“以及”SPFA“即可。在下文内容中,我个人习惯是,起点是 s s s,终点是 g g g.

1.1 松弛

​ 先抛出一个概念,什么是”松弛“?—— 两个点 s s s和 g g g 可以通过第三个点 k k k 作为中转点,来优化、缩短它们之间的距离!如下图所示:

​ Relax
上图就很明显: s s s 到 g g g 直走的距离是999,但是通过 k k k 进行中转的话,距离就会变成2,明显更短了。所以说: s s s 和 g g g 可以通过 k k k 进行松弛操作。而我们“寻找最短路”的过程,实际上就是起点到终点的path,不断被松弛的过程。最短路算法就是变着花样进行松弛。

​ 而松弛过程的代码形式就是:

if( mp[s][g] > mp[s][k]+mp[k][g] ) mp[s][g]= mp[s][k]+mp[k][g];

​ 很直观,很好理解。

1.2 普普通通的Dijkstra

​ Dijkstra算法很常用了,它是 “单源” 最短路算法,采用贪心的思想。即只计算出一个起点到其他端点的最短路信息。只要是单源最短路算法,我们就只需要一维矩阵来保存当前的最短路计算的结果,例: d i s [ i ] dis[i] dis[i] 表示起点 s s s 到节点 i i i 的最短距离值是多少。 也因为是单源最短路算法,我们只需要去关心”源点“到别的点之间的距离是否可以被松弛,任意两个非源点的距离是否被松弛并不care~

  • Dijkstra的思想是什么呢?

    • 贪心的依据: 对于当前的起点 s s s,它如果有好多个直接相邻的邻接点,那么 离他最近的那个邻接点 k k k,肯定是目前、也是未来不需要被松弛、未来也没办法松弛的最近的节点! 明白这个事实以后,我们只需要贪心的选这个节点作为中转点来尝试优化其他所有节点就能一定程度上优化其他的节点了!
    • 注意:Dijkstra用于松弛的中转点的选择,和后续其他算法是不同的!其最大的特点是,每个节点只会被选中一次,也必须被选中一次;被选中一次后,松弛其他所有点;而它们被选中当中转点的时候,它们必然能保证“从那时刻开始自己已经是最优了”而只需要去帮助、松弛别人而已了。
    • 因此,总体Dijkstra的流程就是: 每一次都贪心地枚举 当前状况下离起点 s s s 最近的点 k k k ⇒ \Rightarrow ⇒ 然后尝试其他的点能否通过此点 k k k 进行“松弛”操作 ⇒ \Rightarrow ⇒ 继续选取下一个 k k k.
  • 时间复杂度分析:

    • 根据上面的思路,在有 N N N 个节点的图中,要计算出起点 s s s 到其他各点的最短路,需要 N − 1 N-1 N−1 个节点都完成松弛的中转点的角色(除去起点,每个点都要当一次中转点来松弛其他人。我个人喜欢把起点的初始化也算进去,那就是 N N N轮)。——算法执行 N − 1 N-1 N−1 轮。
      • 每次在寻找中转点的时候,基于上面讲述的“贪心的依据”,是寻找距离起点最近的点(肯定是没选过的才行),所以遍历一遍找最近。——贪心遍历找一个中转点的时间是 O ( N ) O(N) O(N).
      • 用中转点,对其他 N − 1 N-1 N−1个节点进行松弛。——松弛一波是 O ( N ) O(N) O(N).
    • 所以复杂度是 O ( N 2 ) O(N^2) O(N2).
  • Code: 普通Dijkstra的代码

1.3 优先队列(堆)优化的Dijkstra

​ 上述讨论了Dijkstra算法的时间复杂度,如果我们想进一步提升Dijkstra算法的性能我们可以引入“优先队列(堆)” 来实现。其优化、以及实现的思路是:

  • 优先队列优化的Dijkstra的思想是什么呢?

    • 把所有节点都放入到堆里,每次从堆顶取距离最小的节点,完成贪心的过程——从而贪心取一个中转点的时间是 O ( l o g N ) O(logN) O(logN) 虽然取堆顶是 O ( 1 ) O(1) O(1)但是还得更新堆顶…)
    • 我们可以观察到一件事:不用对所有其他 N − 1 N-1 N−1个节点进行松弛操作,而是 仅需要对中转点邻接点进行松弛即可。 不邻接的点怎么可能松弛的了嘛——由于每个中转点对自己的邻接点进行松弛,那么 N − 1 N-1 N−1个中转点以后,就是遍历了两遍边的数量,即 O ( 2 M ) = O ( M ) O(2M)=O(M) O(2M)=O(M)的时间.
    • 总共呢,中转点其实还是只有 N − 1 N-1 N−1个(算上初始化的起点那就是 N N N个)。每一次中转点都会将自己周围的邻接点及其距离源点的信息捆绑在一起然后一同加入到堆里面,因此 同一个节点会同时在堆中有好几个! 所以刚开始堆会很小,到了后来堆会变的很大,最多里面装了 2 M 2M 2M个值(边的数量)。
  • 时间复杂度分析:

    • 很多人对于“优先队列优化的Dijkstra”的时间复杂度写的不一样,这是为什么呢?我刚开始也认为优化以后的Dijkstra是 O ( N l o g N ) O(NlogN) O(NlogN),琢磨了一下发现不对,我的思考如下。
    • 首先回顾一下,堆的特性是每次取堆顶是 O ( 1 ) O(1) O(1),但是pop掉堆顶以后更新下一个堆顶的过程是 O ( l o g N ) O(logN) O(logN),而每次往堆里增加新值堆都需要动态调整也是 O ( l o g N ) O(logN) O(logN)。注:此时在讨论堆的性质时,这里的 N N N表示的是堆内部的值的个数。
    • 为什么网上有说优化以后的Dijkstra是 O ( N l o g N ) O(NlogN) O(NlogN)呢?是这么来的:Dijkstra要取 N − 1 N-1 N−1个中转点,每次从堆里拿一个中转点的时间是 O ( l o g N ) O(logN) O(logN),松弛邻接点的个数虽然不好说,但是所有中转点松弛的次数是 2 M 2M 2M,所以总时间是 O ( N l o g N + 2 M ) = O ( N l o g N ) O(NlogN+2M)=O(NlogN) O(NlogN+2M)=O(NlogN). 但是这个思路是没有考虑上述提到的堆的其他操作的时间复杂度的:堆会越来越大,到后来里面的节点个数有 2 M 2M 2M个,当然也不考虑这个问题,因为假设图是超级稠密图而 M = N × N M=N \times N M=N×N,此时堆取最大值然后更新的时间复杂度依然是 O ( l o g M ) = O ( l o g N 2 ) = O ( 2 l o g N ) = O ( l o g N ) O(logM) = O(log N^2) = O( 2logN ) = O(logN) O(logM)=O(logN2)=O(2logN)=O(logN),一般甚至都不是稠密图,所以写 l o g M logM logM和 l o g N logN logN 都没啥区别;但是要考虑的是,每一次松弛时将周围的邻接点加入到堆中,加一次就要时间 O ( l o g M ) O(logM) O(logM)的时间!整个优先队列优化的Dijkstra过程中,需要最多加入 2 M 2M 2M次邻接点, 所以真正的堆优化的Dijkstra的时间复杂度应该是: O ( N l o g M + M l o g M ) = O ( ( N + M ) l o g M ) = O ( ( N + M ) l o g N ) O(NlogM + MlogM) = O( (N+M)logM ) = O((N+M)logN ) O(NlogM+MlogM)=O((N+M)logM)=O((N+M)logN),)至于是 l o g N logN logN 还是 l o g M logM logM 我上面提到了,我觉得差不多,就可以写一样的~
  • Code: 优先队列优化的Dijkstra的代码

1.4 SPFA算法(含平凡的队列一个)

​ 因为SPFA (Shortest Path Faster Algorithm)算法和堆优化的Dijkstra算法有一丢丢相像,以前我还一度混淆,但是搞清楚它们之间的区别之后,就能更快上手。所以看完上面的堆优化的Dijkstra以后,趁热打铁,就能理解SPFA了。刷简单题什么的,能用SPFA用SPFA,难题就用队列优化Dijkstra了。

  • SPFA算法依然是单源最短路算法。SPFA算法除了快,还有一个优点就是 能处理含有负边与负环的图! 但是Dijkstra算法就不能。

  • 为什么Dijkstra不能跑“含负权的图”:因为Dijkstra从不走“回头路”,每次贪心完的节点不再后续优化松弛了,所以有些时候涉及到负边,跑出来的结果不是最优的。例如:三角形图,给出格式是(起点,终点,边权),那么(1,2,1),(1,3,2),(2,3,-3),的1到2的最优解是-1,但是Dijkstra跑出来是1~

  • SPFA的思想是什么呢?

    • 在谈论SPFA的思想之前, 先要明确Dijkstra的几个关键的特征:①贪心选取最近的点作为中转点;②中转点被选中的时候,其必然是最优状态! ③由②可知,每个节点有且只有一次成为中转点。如果说中转点”松弛“别的点过程像是在帮助别人的话,那么Dijkstra每次选的都是最优秀的人去帮助别人。

    • SPFA的思想是任何人都可以帮助”别人“,即使你不是最优秀的。 SPFA准备了一个 队列 ,里面装的是有可能起到松弛作用的节点。每一次从队列里取出一个节点,尝试对其邻接点进行松弛(为什么是邻接点而不是所有 N − 1 N-1 N−1个点,道理是和队列优化的Dijkstra一样的,因为非邻接的松弛不到呀( ̄▽ ̄)").关键的地方来了:若某邻接点 k k k被松弛了,说明起点到它的距离被优化了!那说明这个 k k k的某些邻接点也可能通过它被松弛呀!就把这个 k k k加入队列中,待会松弛它的邻居!!!正是因为每个人都可以松弛自己周围的人,所以我们不需要去找最优秀的人来专门做中转点进行松弛。这个SPFA会一直找一直找,直到没有任何人能够继续松弛周围的人了,所有人都被榨干了,那么队列肯定就空了,算法就停了!

      ​ SPFA

    • 因为每个人都可以去松弛别人,所以 SPFA中可以出现多条边松弛了一个节点,但是同一时间队列中同一个点只能被压入一次! 毕竟同一个节点在一个队列中出现了好几次也只能表示同一个意思:它想帮助别人。所以SPFA中的book是判断一个点是否在队列里,不需要重复进队,而出队了就把它的标记复位,以后上级被人松弛了依然可以再次进队的。

    • 再次和堆优化的DIjkstra算法进行对比:

      • ①优先队列优化的Dijkstra用的是”优先队列“,实际上是 ”堆“ ;而SPFA用的是真 ∙ \bullet ∙平凡的队列一枚。
      • ②堆优化的Dijkstra压入的是节点ID以及当前与源点的距离,每个节点可以被压入多次,但是其与源点的距离值会变(同一个节点肯定是减少);而SPFA压入的仅仅是节点ID,每个节点也可以被压入多次。
      • ③堆优化的Dijkstra的 book[i]的作用是贪心的时候,判断哪些节点当过中转点了,为了防止重复选择它当中转点;而SPFA的book[i]的作用是判断谁当前在队列里。
      • ④堆优化的Dijkstra再怎么样,依然是贪心思想;而SPFA这种思想,是动规DP。
  • 为什么SPFA算法能检测负环? 一张图里有 N N N个节点,我是结点 k k k,那如果要松弛我,肯定是别的 N − 1 N-1 N−1个节点来松弛我。如果我被松弛了,那我就要进队。我不可能被同一个人重复松弛的! 所以,任意节点(我)被松弛的次数和我进队的次数都不可能超过其他节点的个数也就是 N − 1 N-1 N−1,因此如果出现任何一个节点入队的次数是 ≥ N \geq N ≥N,那说明图中肯定是有负环的。 因为负环会让最短路越走越小,算法会爱上走负环,同时SPFA算法也永远不会结束,是个死循环~

  • 时间复杂度分析:

    • 虽然SPFA的最坏时间复杂度很高,是 O ( N × M ) O(N \times M) O(N×M),但是平均运行的性能很好,类似快排——最坏时间复杂度很高但是平均运行性能不错hh。如果出现卡时间的情况,就改用堆优化的Dijkstra即可。
  • Code: SPFA的代码

1.5 Floyd算法

​ 上面都是难的了,Floyd算法从内容上就显得很简单。这是一个多源最短路算法,运行完以后能知道任意两个节点之间的最短路是多少,当然时间复杂度也是最高的。但是Floyd算法的理解上,我还没有完全理解,只是记住了~同时记录一下我个人常常陷入的错误Floyd理解,引以为戒。

  • Floyd的思想是什么呢?

  • 我个人常常陷入的错误思想: 因为,每个节点作为一次中转点去松弛其他人一次,即,每个节点仅出现一次作用之后,最短路结果就能得到了,所以Floyd的第一层循环 k k k就是枚举每个人去当中转点,后两层循环就是让所有人松弛一波即可。但是,这是完全错误的!而仅仅是代码上看起来是这么回事而已!

    • 首先说为什么是错误的。第一个观点就是错的,并不是“每个节点作为一次中转点去松弛其他人一次,最短路结果就能得到了”,如果这句话是对的,那么Dijkstra里去掉贪心的过程,而是任意选取一个节点作为中转点去松弛别人不就是这句话的思想了吗,难道Dijkstra的贪心过程是完全没有意义的吗?明白了概念上这个观点是错的以后,接下里可以举一个具体的例子来说明这个观点是错的:

      ​ Floyd

      在这张图中,源点是 s s s,如果我们选了 a a a 作为第一个中转点,那么源点到 c c c 的距离肯定不是最优解,因为最优解还需要通过节点 b b b 进行松弛才行。但是因为我们上面的观点是“每个节点作为一次中转点去松弛其他人一次,最短路结果就能得到了”,所以后续的松弛过程中, b b b 节点也仅仅会松弛 a a a 而不会松弛 c c c, 这样显然会导致结果不正确。

    • 所以在求解最短路的过程中,“松弛”与求解最短路的联系是怎么样的呢?上面这句话要怎么修改才能正确呢?我认为,应该是:每个节点作为中转点去松弛其他人一次,并对其他人相关的邻接点、其邻接点的邻接点…(递归下去)都更新因此收到的松弛收益后,那么最短路结果就能得到了!从这个角度上来说,确实是每个节点仅出现一次作用,但是要对其他人完完全全的负责才算“一次作用”!基于这个正确的思想以后,看上图,当我们松弛节点 b b b 的时候, b b b虽然直接松弛了节点 a a a,但是节点 b b b 还需要对 a a a 的后代也就是 c c c 负责,所以要等 a a a 再次松弛一遍节点 c c c, 来将 b b b 的松弛收益贯彻下去才行!而这,就是SPFA的算法思想!

  • 时间复杂度: 看代码,一看就懂, O ( N 3 ) O(N^3) O(N3).

  • Code:

    for(k=1;k<=n;k++)
      for(i=1;i<=n;i++)
          for(j=1;j<=n;j++)
            if(e[i][j]>e[i][k]+e[k][j])
                e[i][j]=e[i][k]+e[k][j];
    

2 网络流复习

  • 基础知识:

    • 普通FF算法:(是一个思想,不讲究到底使用什么算法来寻找增广路的path)

      • C是m条边里面权值最大的值。
      • 每次BFS要m,一共要nC次(如果是整数增广路至少为1,为什么是nC?因为最多情况n个节点都和汇点连接,且权值都为C),所以复杂度是 O ( m n C ) O(mnC) O(mnC).
    • 加速FF算法,此处以EK算法为例子:(基于FF算法的思想,把寻找增广路的过程用BFS来实现,遍历图是O(m))

      • ①n个点之间的中间节点不能包括起点和终点,故中间点数为n-2。
      • ②(u,v))之间是关键边,下一次也是关键边时的起点到u的距离起码增加了2(我也不知道为什么)
      • 这两点能推出(u,v)成为关键边的次数最多为(n-2)/2,而一共有m条边。
      • 所以要BFS的次数是共mn次,EK复杂度为 O ( n m 2 ) O(nm^2) O(nm2).
  • 网络流怎么建图?

    • 我以前普通建图都是用邻接表:vector<Edge> edge[inf];,实现edge[i]表示所有和节点 i i i出发的邻边。但这个形式在这里不行了,因为网络流要保存每次的path,需要记录”边的编号“,而如果采取我习惯的这个存储形式,就没法记录和后续“根据边ID返回修改”。

    • 那应该怎么存储边信息呢?网上的存边的方法是——①每条边存下来 Edge edge[M]; 然后 ②每条边的下标位置建立一个index表,是每个节点的第一条边ID:int pos_edge[M]③每个边多一个next边的ID变量,形成链式结构,SPFA用的时候就用next去追踪下一条边,直至-1。④边的插入的编号是头插法,所以是倒着来的:

      edges[cnt].next = head[from];
      head[from] = cnt;
      
    • 是否要采纳这种存边的方式?如果按我自己来:用一个vector存每个点的邻接边ID——node[N];又用一个数组存每个边的参数——Edge edge[M];然后建立双向的索引,要俩对应的index数组,晕,算了太麻烦了,按网上的来吧。。。

    • Edge类型不用定义起点,因为SPFA中都是从起点直接遍历邻接点,所以存终点即可。

    • 注意,每次建边的时候,要同时建立反向边。所以下标从0开始的话,因为都是成对建边,故 ^ 1 \verb!^! 1 ^1 的异或过程,就可以表示反向边的下标 。

3 费用流入门

  • 不错的网络流模板:网络流模板参考

  • 费用流的代码和普通最大流区别:

    • 费用流的边每次采纳以后,spfa求出来的dis[g]代表的是整条path上的 单位流的费用合 ; 所以spfa结束后我们要根据path上最小的residule的量,来增加流、更新新费用: m i n R e s ∗ d i s [ g ] minRes*dis[g] minRes∗dis[g] ,而不是dis[g];而根据当前的的path,按照最大流的方法,我们把路径上所有path的边的剩余流量 r e s res res参数update掉 ,而 边的“单位费用流”参数完全不会修改的。 也就是说,费用流每次计算完的 d i s [ i ] dis[i] dis[i] 的意义是——从源点到达终点 i i i 的单位流的总费用!
    • SPFA的path怎么存的?不是存每个节点的path父节点的id,因为这样在最后 很不方便去索引边的位置,去update对应的flow值。应该是,每个节点存对应的path上的边的id! 注意,边比点少一个,所以path上的一个点会没有值,写的时候要分清楚自己的顺序,可以存在终点上,源点就空出来不管它。在索引边的时候, i = p a t h [ g ] i=path[g] i=path[g], i i i 是边的id, g g g 是边的终点,那如何知道起点呢?(因为边的参数里只存了终点没存起点,当然也可以自己存进去)起点就是此条边反向边的终点,所以起点就是 s = e d g e [ i ^ 1 ] . t o s=edge[i \verb!^! 1].to s=edge[i^1].to
  • 为什么最小费用最大流( Minimum Cost Maximum Flow, MCMF),使用的SPFA而不是Dijkstra? 因为费用流中的反向边是负权边,所以Dijkstra跑不了,只能用SPFA!当然,SPFA复杂度不稳定,所以那个时候只能用“修正版的Dijkstra”了。

  • 费用流的实现在普通最大流的实现上,有一丝不同:

    • 最大流找到一条path,路径上所有path的边都要进行修改边权。
    • 费用流找到一条path,路径上所有path的边也要进行修改边权,但是在spfa的内部实现过程中是不需要修改边参数的,是只读的(要么完整的用这条边要么就不用)。只在SPFA结束以后才修改一次。
  • Code:

图论算法小结:次短路的求解 利用Dijkstra算法求解次短路 我们曾经学过利用Dijkstra算法求解最短路,但是如果要求解某一个结点的次短路该怎么做呢?实际上,我们仍然可以用Dijkstra算法来求解它。 首先来回顾一下Dijkstra算法的原理:首先把所有结点的最短距离设置为无穷大,然后令d[0]=0。接下来,每次都找到最短路已经确定的经典,更新从它出发的相邻结点的最短距离。以后我们不再考虑最短距离已经确定 阅读详情

相关推荐

VMware共享磁盘配置实战:从零搭建多机共享存储环境

本文详细介绍了在VMware环境中从零开始配置共享磁盘的完整实战流程。通过创建共享磁盘、挂载至多台虚拟机并修改.vmx配置文件等关键步骤,帮助用户搭建可用于数据库集群(如Oracle RAC)测试的多机共享存储环境,并提供了核心参数设置与常见问题排查指南。

weixin_29284201的博客 490

[学习笔记]网络流/费用流总结

这几天集中学习了一下有关网络流/费用流的问题。 自己之前也没有较为深入地研究过,只是打了几道板题然后就咕咕了。 [补]这篇博客本来该一周之前就发布的,结果忘掉了。

Panda_Hu's blog 2466

Python量化入门:用pytdx获取800个交易日K线数据的完整指南(附代码)

本文为Python量化交易初学者提供了使用pytdx库免费获取股票日线级别K线数据的完整指南。文章详细介绍了从环境搭建、单只股票数据获取,到构建健壮的批量下载器、数据清洗与验证,再到基础分析与可视化的全流程,并附有可直接运行的代码示例,帮助读者快速建立本地股票数据库。

weixin_29050513的博客 1462

网络流之费用流

求费用流目前好像只有EK+SPFA改版,时间复杂度为O(N*E*k),其中K为最大流值。但时间上的期望时间复杂度为:O(A*E*K),其中A为所有顶点进队列的平均次数,可以证明A一般小于等于2。 最小费用最大流: #include using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 205; struct

yo_bc的博客 3607

【Pico手势开发实战】基于SteamVR串流与MRTK3的跨平台交互方案

本文详细介绍了在Pico设备上,结合SteamVR串流与微软MRTK3框架,实现高效跨平台手势交互开发的完整方案。该方案通过在PC端运行Unity项目并串流至头显,利用MRTK3封装的手势识别与交互组件,大幅提升了开发调试效率与性能上限,并确保了未来向其他OpenXR设备的良好兼容性。

weixin_29001683的博客 216

ESWA投稿全流程避坑指南:从LaTeX模板到审稿状态查询(附最新资源链接)

本文提供了一份详尽的ESWA期刊投稿全流程指南,涵盖从LaTeX模板深度适配、Cover Letter撰写,到Editorial Manager系统操作、审稿状态解析等关键环节。重点解析了投稿准备中的常见“雷区”与文件合规性要求,并分享了收到审稿意见后的高效修改与回复策略,旨在帮助研究者规避流程陷阱,提升投稿效率与成功率。

9o8p7i6u5y的博客 838

网络流最大流,费用流

网络流,指的是在一个每条边都有容量的有向图分配流,使得一条边的流量不会超过他的容量有向图称为网络,顶点称为结点,边称为弧源点:只出不进的顶点汇点:只进不出的顶点容量和流量:每条有向边上有两个两,容量和流量。

Se_ren_di_pity的博客 1238

DAP-Link DIY复刻指南

DAP-Link是ARM开源的一个项目,主要用于代码下载以及调试,支持SWD和JTAG调试接口,对于开发嵌入式的同学相信都或多或少有所耳闻。除了DAP-Link之外还有很多同类型的调试器,如ST-LinkJ-Link,但是这些都是不开源的,无法复刻或进行二次开发。但DAP-Link不同,完全开源,不用担心侵权问题,且随着开源社区大家的共同努力,DAP-Link经过了不断的迭代,先如今已取代ARM之前推出的CMSIS-DAP开源项目。

爱出名的狗腿子 1万+

图论-网络流⑦-费用流解题

图论-网络流⑦-费用流解题① 上一篇:图论-网络流⑥-费用流① 下一篇:未完待续 参考文献: 暂无 大纲 什么是网络流 最大流(最小割) DinicDinicDinic (常用) EKEKEK SapSapSap Ford−FulkersonFord-FulkersonFord−Fulkerson(不讲) HLPPHLPPHLPP (快) 最大流解题 费用流 EKEKEK...

KonnyWen的博客 651

一文解释电路中常用电子元器件应用和选型01

电容和二极管是电路中最常用的两个电子元器件,种类和系列众多,这里简单总结一下应用场景和选型方式 电容(Capacitor) 电容的种类(20种以上)和应用非常广泛,但是我经常遇到的无非就是下面这几种: 应用 1.隔直流。 2.旁路(去耦) 3.耦合 4.滤波 5.温度补偿 6.计时 7.调谐 8.整流 9.储能 种类 1. 陶瓷电容 2. 云母电容 3. 铝电解电容 4. 钽

weixin_43904073的博客 2236

关于瑞芯微SDK中buildroot的架构分析、配置细节、以及一些使用步骤

摘要:瑞芯微SDK基于Buildroot框架,针对RK3568等芯片提供定制化开发环境。核心目录包括buildroot(配置与编译框架)、kernel(定制内核)和u-boot(引导程序)。开发流程为:1)加载芯片默认配置;2)通过menuconfig定制系统(架构、内核、软件包等);3)可选修改内核配置。关键硬件适配需修改设备树(dts)和分区表(parameter.txt),系统行为通过启动脚本(S90network)调整。最终执行make编译生成可烧录固件。该框架通过配置文件驱动,实现从工具链构建到固

Hyjks的博客 1199

最短路练习

每想到一些天地都容纳不下的说法心里就烧起烟霞没去过心上人流浪的白发天涯哪里懂镜月水花。

ZZZS0516的博客 936

本地部署大模型:dgx-spark-ai项目硬件选型、部署与私有化AI构建指南

大语言模型(LLM)的本地部署是当前AI工程实践中的重要方向,其核心原理在于将模型权重与计算过程完全置于用户可控的硬件环境中。这项技术的核心价值在于实现了数据主权与隐私安全,避免了云端服务的延迟、持续订阅成本及数据外泄风险。从技术实现看,本地部署的关键在于硬件选型与软件环境适配,尤其是NVIDIA GPU的CUDA生态、显存容量与内存带宽的匹配。在应用场景上,本地化部署特别适合对数据敏感性要求高的领域,如企业内部代码助手、金融分析或医疗研究,能够支持私有化模型微调与定制化工作流构建。本文以dgx-spark

weixin_42531579的博客 502

以入门基础理解最短路算法#2 BFS 与 DFS 、存图、STL(最短路算法必要基础)Part 1

上一篇文章 从入门角度深入理解——有关最短路的常见算法#1 最短路问题介绍。 点这里看上一篇 简单介绍了图的基本知识、最短路问题的分类情况。 可以让我们对求解最短路问题有个角度。 这告诉我们,写最短路问题时要考虑: 是否有权 是有向图还是无向图 是否有负环 有了思考的角度。 我们还需要掌握一些基本的工具。 如果说上一篇文章是在我们思考该从哪个角度。 那么这篇文章就是学习 ...

wdshhh的博客 2351

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

【小结】最小费用流&最大权闭合图

最小费用流就是在保证流量FF的前提下,求解最少花费是多少的问题O_O{O\_O} 建图: 每条边在最大流基础上(to指向点,cap容量,rev反向边)\left(to指向点,cap容量,rev反向边\right),增加一个费用(cost)\left(cost\right) 求解方法: 在最大流中,是按照任意可行路径,也就是残余网络中的可增广路径,向网络中注入流量,从而在汇点获得相应流量的策略进行,直

When you go away 982

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

最短路径 模板小结

——————————————————————————————————————————————————第一次写最短路径留念,顺便小结一下模板。最短路有诸多算法,如SPFA、Dijketra、floyd……这里介绍两种最常用的模板Dijketra和floyd 模板。Dijketra———————————————————————————————————— 相当于从出发点开始,每次选取最短的那条边,把边的

Nodies 614

程序设计基础课程设计 —— 学校地图信息库系统

通过本课程设计,实现一个学校地图信息库系统,可以很好的发挥自己的想象力和动手能力。(1) 掌握最短路径的Dijkstra和Floyd的算法使用;(2) 利用文件来保存程序运行的数据信息;(3) 学会了二维数组对字符串的了解和运用;(4) 学会了使用打开文件和保存文件和输入的相关代码;(5) 全局变量的定义和使用。

ZShiJ的博客 1175

【狂热算法篇】探秘图论之Dijkstra 算法:穿越图的迷宫的最短路径力量(通俗易懂版)

在复杂的图结构中,我们如同置身迷宫,迷失于节点与边的交织。Dijkstra 算法恰似神奇力量,它闪耀着智慧光芒,为我们指引方向。凭借其独特逻辑,在节点间高效穿梭,巧妙更新距离,精准筛选路径,迅速找出最短路径,助你轻松穿越图的迷宫,是解决最短路径问题的不二之选,带你开启高效寻径之旅。

羑悻的博客. 3万+

【研一周小结】第三周个人学习总结

第三周学习总结 21-03-15【太困】 SIST Yippee 1 算法设计与分析 本周讲了两部分内容,动态规划(DP)后部分,以及网络流前部分。 动态规划 RNA序列内部最大匹配问题 给一个RNA序列——由A、U、G、T组成的串,对任意两项配对成功则连条线,求“不存在交叉线”下的最大配对可能数。 如果令OPT(i)表示前i个串下,符合题意的最大配对数是OPT(i),是行不通的——没办法联系出“子串”间的关系。 应为OPT(i,j)表示从i到j的子串,符合题意的最大配对数是OPT(i,j)。分

Hide_in_Code 369

算法学习(五)图算法学习总结

文章目录图算法1、图的表示2、图的遍历2.1、BFS(宽度优先搜索、优先队列)2.2、DFS(深度优先搜索、递归算法)3、寻找最小生成树3.1、Prim算法3.2、 Kruskal算法4、最短路径问题4.1、单源最短路径问题4.2、所有点对最短路径问题 图算法 1、图的表示 2、图的遍历 2.1、BFS(宽度优先搜索、优先队列) 对边搜索、不断延展。 2.2、DFS(深度优先搜索、递归算法) 递归调用顶点 3、寻找最小生成树 3.1、Prim算法 3.2、 Kruskal算法 4、最短路

LH is programming hard 1954

基础算法小结

王红梅 胡明 算法

耿直boy 571

【算法设计与分析】贪心算法

本文介绍了贪心算法的核心思想和应用场景,重点分析了活动安排问题的贪心解法。贪心算法通过每步做出局部最优选择(如按结束时间最早优先)来构造全局最优解,相比动态规划具有更低复杂度。文章详细阐述了活动安排问题的贪心策略设计、正确性证明及Python实现,并通过示例展示了算法执行过程。贪心算法适用于具有贪心选择性质的问题,如活动安排、哈夫曼编码等。

m0_72516377的博客 1098

数据结构期末复习小结

文章目录最小生成树Kruskal(克鲁斯卡尔)算法prime(普利姆)算法最短路Floyd(弗洛伊德)算法Dijkstra(迪杰斯特拉)算法哈夫曼编码确定权值建树编码等长编码拓展与思考邻接表和邻接矩阵平衡二叉排序树问题平衡树思想哈希线性探测法例题链地址法例题排序树小结顺序表操作集带头结点的链式表操作集树的四种遍历 最小生成树 Kruskal(克鲁斯卡尔)算法 最小生成树,算法思想:首先按照边的权值进行从小到大开始排序,每次从剩余的边中选择权值较小的且边的两个顶点不在同一个集合内的边,加入到生成树,直到n-1

ZZULI_星.夜 3326

贪婪算法小结

背景介绍:贪婪算法可以说是离我们生活最近的一种算法,人总是贪婪的嘛,所以这种算法的设计是很符合人性的。之所以这么说,是因为人们会在生活中有意无意的使用贪婪算法来解决问题。最常见的就是找零钱了,每个人都没学过该怎么找零钱,但在所有面额的钱都充足时,每个人都会找出同样组合来凑够需要的钱。其实这里面就是贪婪算法在起作用。 设计思路:贪婪法的设计思路可以从两方面来理解,即直观上和数学上。从直观上理解贪婪

让代码改变世界 1万+

算法学习之二叉树系列小结

文章目录二叉树递归104. 二叉树的最大深度层次遍历102. 二叉树的层序遍历前中后序遍历BST98. 验证二叉搜索树Tire 二叉树 递归 对于递归类型的题,首先是三点: 这个递归函数的功能是什么,怎样调用这个函数,即设计好递归函数的返回值和参数列表 什么时候应该结束这个递归,它的边界条件(出口)是什么 (边界条件) 在非边界情况时,怎样从第n层转变成第n+1层 (递推公式) 104. 二叉树的最大深度 给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。 说明:

Suarge的博客 1003

【贪心算法】一文让你学会“贪心”(贪心算法详解及经典案例)

贪心算法是一种非常常见的算法,它的简单和高效性使其在实际应用中被广泛使用。 贪心算法的核心思想是在每一步都采取当前状态下最优的选择,而不考虑未来可能产生的影响。虽然贪心算法不能保证总是得到最优解,但在很多情况下,它可以获得很好的结果。 本篇文章将介绍贪心算法的基本概念和一些经典应用,以及如何通过贪心算法来解决一些实际问题。希望通过本文的阅读,读者可以对贪心算法有更加深刻的理解,并能够在实际问题中应用贪心算法来得到更好的解决方案。 让我们暴打贪心算法吧!

m0_69383623的博客 5335
上一篇: 【研一周小结】第十周个人学习总结
下一篇: 【研一课程】算法设计与分析 FInal OJ解题报告
仰天倀笑
博客等级 码龄10年 313粉丝 124原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值