最短路算法汇总

校赛完了,这次校赛,做的很差,一个算法题没有,2个水题,1个贪心,概率DP,DP,数论题。DP还没开始研究,数论根本不会,数学太差了,省赛时卡数论,校赛依然卡数论,我擦,还是得继续学习啊!

一把锈迹斑斑的剑,只有不断的磨砺,才能展露锋芒!

以下为最短路总结:

最短路问题可分为:

一、单源最短路径算法,解决方案:Bellman-Ford算法,Dijkstra算法,SPFA

二、每对顶点间的最短路径算法:Floyd;

(1).Dijkstra算法:

(经典的算法,可以说是最短路问题的首选事例算法,但是不能处理带负权的边,因为该算法要遍历的点过多,效率低下,用时长,仅限于小数据,不常用)

基本思想:

Dijkstra算法,本质上是利用贪心思想来不停的来进行贪心选择,查找最优解,开辟一个s[],用来存放这些点,

dis[]用来存放所能经过的每个点的最短距离,并进行dis[]的更新操作。

模版如下:

   int m,n,map[max][max],dis[max],s[max];
//int prev[max];//当前点的上一个节点

    void Dijkstra(int v0)
  {
    for(int i = 0;i<n;i++) //初始化dis[]
    {
        s[i] = 0;
        dis[i] = map[v0][i];
     /*   if(i!=v0 && map[v0][i]<inf)
        prev[i] = v0
         else
        prev[i] = -1;  */
    }
    s[v0] = 1;
    dis[v0] = 0;
    for(int i = 2;i<=n;i++)
    {
        int u = v0,min = inf;
        for(int j = 0;j<n;j++)//贪心查找还未存储的最优解的点,并储存
        {
            if(!s[j] && dis[j] < min)
            {
                u = j;
                min  = dis[j];
            }
        }
        s[u] = 1;
        for(int j = 0;j<n;j++)//更新dis[]数组
        {
            if(!s[j] && map[u][j] < inf && dis[u] + map[u][j] < dis[j])

            {
                 dis[j] = map[u][j] + dis[u];
                 //prev[j] = u;
             }

        }
    }
  }

(2).Bellman-Ford

(用来判断是否有回环,可处理带负权边 时间复杂度O(V*E).)

基本思想:(DP思想,查找最优解,并不断的进行松弛操作,但是算法浪费了许多时间做冗杂的松弛操作,效率降低)

void add()
{
    scanf("%d%d%d",&u,&v,&w);
    edge[l].u = u; edge[l].v = v; edge[l++].w = w;
    edge[l].u = v; edge[l].v = u; edge[l++].w = w;
}

int Bellman(int cnt)
{
    int i,j,flag;
    for(i = 1;i <= N - 1;i++)
    {
        flag = 0;
        for(j = 0;j <= count - 1;j++)
          {
              if(dis[edge[j].u]> dis[edge[j].v] + edge[j].w)
                {    //松弛计算
                dis[edge[j].u] = dis[edge[j].v] + edge[j].w;//更新dis[]数组,使其存储 源点->当前点的最短距离
                flag = 1;
                }
          }
        if(flag==0)//如果查找完,或者有些点达不到,跳出
            break;
    }
    for(i = 0;i < count;i++)//判断是否有负环路
        {
            if(dis[edge[i].u] > dis[edge[i].v] + edge[i].w)//更新完dis[]后,如果还存在 该成立条件,则存在负环路
            return 1;
        }                                              //  如1->2 权值2
    return 0;                                         //     2->3 权值5
                                                      //     3->1 权值-8
                                                    //       1->2->3->1 一次循环为-1 二次-2  三次....
}

(2)FLOYD

这个实在没什么好说的,做题目时,只要确定的 时间不超,就可以用,前提是记下,时间复杂度O(n*n*n).

 void init()
{
         for(i=0;i<n;i++)
        for(j=0;j<n;j++)
        {
           map[i][j] = (i==j)?0:inf;
        }
 }
void floyd()
{
         for(k=0;k<n;k++)
      {
          for(i=0;i<n;i++)
            {
                for(j=0;j<n;j++)
                {
                  if(map[i][k]!=inf && map[k][j]!=inf && map[i][j]>map[i][k] + map[k][j] )
                   {
                    map[i][j]=map[i][k]+map[k][j];
                   }
                 }
             }
      }
}

(4)SPFA

书上说是在bellman-ford的基础上,添加一个队列操作,减少了其不必要的松弛操作。

我个人认为是在BFS搜索的基础上加了一步所谓的松弛操作,至于为什么叫松弛,不懂。

但是SPFA优化的很棒,以后最短路问题,尽量用它

void SPFA(int s,int e)   S点 到e点
{
    int l,r,i;
    l=r=0;
    memset(vt,0,sizeof(vt));
    for(i=0;i<n;i++)
    dis[i]=inf;
    dis[s]=0;
    q[r++]=s;//进队列
    vt[s]=1;//标记 进队列1
            //不在队列为0
    while(l<r)
    {
        int p=q[l++];//出队列
        for(i=0;i<n;i++)
        {
            if(dis[i]>dis[p] + map[p][i])
            {
                dis[i] = dis[p] + map[p][i];
                if(!vt[i])
                {
                    q[r++] = i;
                    vt[i] = 1;
                 }
            }
        }
        vt[p] = 0;
    }
    if(dis[e]!= inf)
    printf("%d\n",dis[e]);
    else
    printf("-1\n");
}

最短路算法汇总,布布扣,bubuko.com

时间: 2024-12-09 16:34:14

最短路算法汇总的相关文章

最小生成树算法汇总 (普里姆 &amp;&amp; 克鲁斯卡尔与并查集结合)

最小生成树: 今天研究了一下最小生成树,感觉最小生成树算法与最短路算法 相差不大,从Prim 与 Dijskrs算法可以看出 最小生成树即最小权重生成树,主要适用于 N个点之间 构造N-1线路,使N个点之间任意两点之间都可到达, 但是N个点之间 不构成回路,并且这N-1条线路的权重之和最小即 消耗最小. 注意:在构造最小生成树,加入新的节点时,不仅要保证权重最小,首要条件是 不能构成回路. 以图示为例,构造最小生成树 (一)普里姆   以下步骤 (二) 克鲁斯卡尔 最终的最小生成树 和 普里姆一

【啊哈!算法】算法7:Dijkstra最短路算法

上周我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短路”.本周来来介绍指定一个点(源点)到其余各个顶点的最短路径,也叫做“单源最短路径”.例如求下图中的1号顶点到2.3.4.5.6号顶点的最短路径. <ignore_js_op> 与Floyd-Warshall算法一样这里仍然使用二维数组e来存储顶点之间边的关系,初始值如下. <ignore_js_op> 我们还需要用一个一维数组dis来存储1号顶点到其余各个顶点的初始路程,如下.

排序算法汇总总结_Java实现

一.插入排序 直接插入排序(Insertion Sort)的算法描述是一种简单直观的排序算法.它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入.插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间. 代码实现: public class Inseretion_Sort {     public static void main(Stri

最短路算法及其延伸

个人算法训练题集:http://acm.hust.edu.cn/vjudge/contest/toListContest.action#contestType=0&contestRunningStatus=0&contestOpenness=0&title=风斩冰华&manager= 密码xwd,欢迎大家一起来学习. 首先复习一下最短路问题,即求某两点之间边权最小的一条路径.这样就延伸出了两个子问题: 求任意两点的距离,还是求图上固定一个起点到某点的距离? 验题:http:

【啊哈!算法】算法6:只有五行的Floyd最短路算法

暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有4个城市8条公路,公路上的数字表示这条公路的长短.请注意这些公路是单向的.我们现在需要求任意两个城市之间的最短路程,也就是求任意两个点之间的最短路径.这个问题这也被称为“多源最短路径”问题. 现在需要一个数据结构来存储图的信息,我们仍然可以用一个4*4的矩阵(二维数组e)来存储.比如1号城市到2号城市的路程为2,则设e[1][2]

最短路算法大杂烩

最短路算法主要有以下几个: 一 Dijkstra 二 Bellman-Ford 三 SPFA 四 ASP 五 Floyd-Warshall 首先约定一下图的表示: struct Edge{         int from,to,wt;     };     vector<int>G[N];     vector<Edge>G[N]; -------------Dijkstra算法 使用条件:无负权边 复杂度O:((V+E)*log(V)) 下面是用优先队列实现的Dijkstra算

近十年one-to-one最短路算法研究整理【转】

前言:针对单源最短路算法,目前最经典的思路即标号算法,以Dijkstra算法和Bellman-Ford算法为根本演进了各种优化技术和算法.针对复杂网络,传统的优化思路是在数据结构和双向搜索上做文章,或者针对不必要的循环进行排除.近年来,最短路算法大量应用于需要高及时性的领域,比如GIS领域,也大量应用于网络规模巨大的社会网络分析领域,这使得传统思路并不能很好地解决,于是把最短路算法思路本身抽象成两阶段算法,第一阶段为数据预处理,第二阶段为实时地搜索.这二者是互相矛盾的,如何找到平衡是各种算法技术

排序算法汇总(C/C++实现)

前言:     本人自接触算法近2年以来,在不断学习中越多地发觉各种算法中的美妙.之所以在这方面过多的投入,主要还是基于自身对高级程序设计的热爱,对数学的沉迷.回想一下,先后也曾参加过ACM大大小小的校级赛.区域赛.没什么惊天动地的奖项,最好的名次也就省三等奖.现在作为第一篇算法总结就拿常见的排序算法以我个人的理解,以及代码实现跟大家简单分享一下(排序算法如果一一罗列的话,不下十种.曾在图书馆的旧书架上看过一本近900页的书,内容就是专门介绍排序算法). 选择排序(select) 选择排序比较容

转载:各种排序算法汇总

转载地址:http://www.cnblogs.com/wolf-sun/p/4312475.html 各种排序算法汇总 目录 简介 交换排序 冒泡排序 快速排序 插入排序 直接插入排序 希尔排序 选择排序 简单选择排序 堆排序 归并排序 基数排序 总结 简介 排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记 录序列.分内部排序和外部排序.若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序.反之,若参加排序的记录数量很大,整个序列的排序过 程不可