最短路

最短路,顾名思义就是对于一个连通图求起点到终点的最短距离:
       
①Floyd:
         
 
这是利用动态规划思想求得任意两点间的最短路,很简单;
            用dp[i][j]记录i到j的最短路长度,枚举i和j,再枚举一个k,若i到k的当前最短路与j到k的当前最短路之和大于i到j的当前最短
        路,则更新dp[i][j],即dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]),主程序段如下:

for (int i=1;i<=n;i++)
    for (int j=i+1;j<=n;j++)
        for (int k=1;k<=n;k++)
            dp[i][j]=max(dp[i][j],dp[i][k]+dp[k][j]);

时间复杂度:O(n^3),并不高效。
        ②SPFA:
         
 
这是采用从起点出发,向外不断扩展更新的方法;
            先维护一个队列,开始时起点入队,每次从队列中拿出一个点i,枚举它的所有边,若从起点到i的当前最短路与此边之和大
        于起点到该边另一点的当前最短路,则更新之,再放进队列,主程序段如下:

           while(!dq.empty()){
                x=dq.front();
                dq.pop_front();
                in_queue[x]=false;
                for(i=0;i<adjmap[x].size();i++){
                    to=adjmap[x][i].to;
                    if((dist[x]<INF)&&(dist[to]>dist[x]+adjmap[x][i].weight)){
                        dist[to]=dist[x]+adjmap[x][i].weight;
                        path[to]=x;
                        if(!in_queue[to]){
                            in_queue[to]=true;
                            in_sum[to]++;
                            if(in_sum[to]==nodesum)
                            returnfalse;
                            if(!dq.empty()){
                                if(dist[to]>dist[dq.front()])
                                dq.push_back(to);
                                else
                                dq.push_front(to);
                            }
                            else
                            dq.push_back(to);
                        }
                    }
                }
            }

期望的时间复杂度:O(k*n^2), 其中k为所有顶点进队的平均次数,n为总顶点数,可以证明k一般小于等于2。 SPFA还有
        SLF,LLL,滚动数组等优化。
        ③Dijkstra:
            这是按路径长度递增次序产生最短路;
            把顶点集合V分成两组:

(1)S:已求出的顶点的集合(初始时只含有源点V0);

(2)V-S=T:尚未确定的顶点集合;

将T中顶点按递增的次序加入到S中,保证:

(1)从源点V0到S中其他各顶点的长度都不大于从V0到T中任何顶点的最短路径长度;

(2)每个顶点对应一个距离值;

S中顶点:从V0到此顶点的长度;

T中顶点:从V0到此顶点的只包括S中顶点作中间顶点的最短路径长度;

依据:可证V0到T中顶点Vk的,或是从V0到Vk的直接路径的权值;或是从V0经S中顶点到Vk的路径权值之和(反证法
        可证);
            另外,据说可以用堆优化(可惜我还不太会),主程序段如下:

       while(count<n)
              {
                  tempmin=INFINITE;
                  for(i=1;i<=n;i++)
                  {
                      if(in[i]==0&&Len[i]<tempmin) //find the smallest one
                      {
                          tempmin=Len[i];
                          si=i;
                      }
                  }
                  in[si]=1;
                  count++;
                  for(i=1;i<=n;i++) //updata the length
                  {
                      if(in[i]==0&&(tempmin+mGraph.matrix[si][i])<Len[i])
                      {
                          Len[i]=tempmin+mGraph.matrix[si][i];
                      }
                  }
              }    

时间复杂度为:O(n^2),堆优化的话时间复杂度为:O((m+n)logn)。我已开始了解它的基本思想后自己竟打出了个SPFA
        的说,个人觉得它是SPFA的优化版,只不过加了个每次枚举时当前未标记的点中路径最短的即为此点的最短路,然后就不用
        每次把它放入队列了,时间复杂度也就少了个k,个人觉得。
            它是目前已知求单源最短路效率最高的一种,若求的是全源最短路,就对每一个点做一次,时间复杂度为O(n^3),事实上
        也就和Floyd一样。
     
  ④Bellman-Ford:
            这是求含负权图的单源最短路径算法;
            进行不停地松弛(原文是这么写的,为什么要叫松弛,争议很大),每次松弛把每条边都更新一下,若n-1次松弛后还能更
        新,则说明图中有负环,无法得出结果,否则就成功完成,主程序段如下:

        for(int i = 1; i <= nodenum; i++) //初始化
            dis[i]= (i == original ? 0 : MAX);
        for(inti = 1; i <= nodenum - 1; i++)
            for(intj = 1; j <= edgenum; j++)
                if(dis[edge[j].v]> dis[edge[j].u] + edge[j].cost) //松弛(顺序一定不能反~){
                    dis[edge[j].v]= dis[edge[j].u] + edge[j].cost;
                    pre[edge[j].v]= edge[j].u;
                }
        boolflag = 1; //判断是否含有负权回路
        for(inti = 1; i <= edgenum; i++)
        if(dis[edge[i].v]> dis[edge[i].u] + edge[i].cost){
            flag= 0;
            break;
        }

时间复杂度为O(nm),其中n为点数,m为边数

    完……

时间: 2024-10-06 13:51:40

最短路的相关文章

hdu3461Marriage Match IV 最短路+最大流

//给一个图.给定起点和终点,仅仅能走图上的最短路 //问最多有多少种走的方法.每条路仅仅能走一次 //仅仅要将在最短路上的全部边的权值改为1.求一个最大流即可 #include<cstdio> #include<cstring> #include<iostream> #include<queue> #include<vector> using namespace std ; const int inf = 0x3f3f3f3f ; const

UESTC30-最短路-Floyd最短路、spfa+链式前向星建图

最短路 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的T-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据. 每组数据第一行是两个整数NN ,MM (N≤100N≤100 ,M≤10000M≤1000

ACM: HDU 2544 最短路-Dijkstra算法

HDU 2544最短路 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗? Input 输入包括多组数据.每组数据第一行是两个整数N.M(N<=100,M<

ACM/ICPC 之 昂贵的聘礼-最短路解法(POJ1062)

//转移为最短路问题,枚举必经每一个不小于酋长等级的人的最短路 //Time:16Ms Memory:208K #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; #define INF 0x3f3f3f3f #define MAX 105 int lim, n; int p[M

图论(A*算法,K短路) :POJ 2449 Remmarguts&#39; Date

Remmarguts' Date Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 25216   Accepted: 6882 Description "Good man never makes girls wait or breaks an appointment!" said the mandarin duck father. Softly touching his little ducks' head, h

hdu4725 拆点+最短路

题意:有 n 个点,每个点有它所在的层数,最多有 n 层,相邻两层之间的点可以互相到达,消耗 c (但同一层并不能直接到达),然后还有一些额外的路径,可以在两点间互相到达,并且消耗一定费用.问 1 点到 n 点的最小花费 将每一层拆成两个点,分别为进入层和出发层,然后相邻层的出发层可以指向进入层,花费 c,每个点可以到达其出发层,而进入层可以到达该点,花费 0 ,最后建立其余双向边,最短路 1 #include<stdio.h> 2 #include<string.h> 3 #in

hdu3416 最短路+最大流

题意:有 n 点 m 边,有出发点 A 到达点 B ,只允许走原图中的最短路,但每条边只允许被走一次,问最多能找出多少条边不重复的最短路 一开始做到的时候瞎做了一发最短路,WA了之后也知道显然不对,就放着了,后来打了今年的多校,再做到的时候发现和多校第一场的1007一样的……最短路+网络流就行了,只不过第一次做这个的时候我还不知道网络流是啥,不会做也正常啦. 首先对于原图跑一遍最短路求出每个点距离 A 点的最短路,然后对于每一条边,如果它的权值等于它连接的两点的最短路的差值的时候,就说明这条路是

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

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

HDU ACM 2544 最短路-&gt;最短路

最短路,简单题,floyd实现,在求最短路时一定要是是最大节点编号maxnum而不是输入的n,否则是错的. #include<iostream> using namespace std; int map[105][105]; //无向图 void Init() { int MAX=1000000,i,j; for(i=1;i<=104;i++) for(j=1;j<=104;j++) if(i==j) map[i][j]=0; else map[i][j]=MAX; } void

POJ 1135 Domino Effect(最短路 多米诺骨牌)

题意 题目描述: 你知道多米诺骨牌除了用来玩多米诺骨牌游戏外,还有其他用途吗?多米诺骨牌游戏:取一 些多米诺骨牌,竖着排成连续的一行,两张骨牌之间只有很短的空隙.如果排列得很好,当你推 倒第 1张骨牌,会使其他骨牌连续地倒下(这就是短语"多米诺效应"的由来). 然而当骨牌数量很少时,这种玩法就没多大意思了,所以一些人在 80 年代早期开创了另一个 极端的多米诺骨牌游戏:用上百万张不同颜色.不同材料的骨牌拼成一幅复杂的图案.他们开创 了一种流行的艺术.在这种骨牌游戏中,通常有多行骨牌同时