zoukankan      html  css  js  c++  java
  • 最短路径问题小结

    最短路径问题包括:

    1、单源最短路。

    2、任意两点间的最短路。

    3、次短路和k短路。

    4、差分约束系统。

    5、DAG图上的单源最短路。

    6、最小环。

     

    一、单源最短路

    算法: Dijkstra 、 Bellman - Ford SPFA

    Dijkstra: 除了路径记录和更新距离数组的部分意外,和Prim算法的实现完全一样。使用邻接矩阵建图,时间复杂度为O(n*n)。使用邻接表可能会快一些。堆优化比较麻烦,没学。缺点是图中不能含有负圈。

    Bellman - Ford :可以处理负圈。以链式前向星建图,时间复杂度为O (n*m)

    SPFA: 优化的Bellman - Ford算法,可以处理负圈。期望的时间复杂度为O(k*m),k<=2。普遍认为其效率高于朴素的Dijkstra,低于堆优化的Dijkstra

    题目:

    多源转单源  hdu2066一个人的旅行(是谁说新手刷杭电11页的,学了最短路还卡了很久)

    来回最短路(有向图建反向图  hdu1535Invitation Cards 

    有限制的最短路   hdu3873 Invade the Mars   http://www.cnblogs.com/Potato-lover/p/3955179.html

    二分法求带限制的最短路  hdu2962 Trucking   (二分查找的应用实在太广了,二分匹配、网络流都有二分技术)

    (综合题)强连通+最短路 poj3114  

     

    二、任意两点间的最短路

    解决的问题:给出一幅图(有向或者无向),有多次询问,问任意两点之间的最短距离是多少。

    暴力的方法:运行多次最短路算法。一般这种题目的数据量大,此算法复杂度太高,不适用。

    Floyd算法:邻接矩阵建图,三重循环,时间复杂度为O(n*n*n)

    提醒:初学者一般会把算法混淆。比如说,把这种题目理解为LCA问题,然后用离线的Tarjan算法来做,时间复杂度是Om+q,不是更快么?需要知道的LCA问题是指树的最近公共祖先,其解题范围是树。对于有环的图是无能为力的。

    题目:

    输出最短路的路径(字典序最小 hdu1385Minimum Transport Cos    传送门:http://www.cnblogs.com/Potato-lover/p/3959795.html

     

    三、次短路和k短路

    字面上看次短就是第二路边,归结到K短路就可以了。实现却不能这样做,原因是算法的实现不能这样做。说到底还是时间复杂度的问题。

    次短路是通过修改Dijkstra算法而实现的。时间复杂度是O(n*n)

    K短路是通过SPFA+A*实现的。如果只求K短路的值效率挺高的,但是如果要求与K短路值相同的路径有多少条,这个就很复杂了。

    暴力的方法:求一遍最短路,记录路径并记录任意两点之间的路径之间的最大边,枚举所有边。(类似与Prim暴力求次小生成树)。

    下面是K短路的实现:

    SPFA + A* 实现K短路

    K短路要用到A*算法,A*算法通过一个估价函数f(h)来估计途中的当前点p到终点的距离,并由此决定它的搜索方向,当这条路径失败时,它会尝试其他路径。对于A*,估价函数 当前值 当前位置到终点的距离, 即f (p) = g (p) + h (p) ,每次扩展估计函数值最小的一个。对于K短路算法来说,g (p) 为当前从sp所走的路径的长度,h (p)为从点pt的最短路的长度,则f (p)的意义就是从s按照当前路径走到p后再走到终点t一共至少要走多远。

    具体实现步骤:

    使用链式前向星来存储图由于需要预处理所有的点到终点T的最短路径,就需要将图G中所有的边反响得到G1再从终点T做单源最短路径,所以实际上是两张图。

    1、将有向图的所有边反向。以T(终点)为源点,求解T到所有点的最短距离。这一步可以用Dijkstra 或者 SPFA算法。我用的是 SPFAshortest  path  faster  algorithm)。

    2、新建一个优先队列,将源点S加入到队列中。

    3、从优先队列中弹出f (p)最小的p,如果点p就是t ,则计算t出队的次数,如果当前为T的第K次出队,则当前路径的长度就是st的第K短路的长度,算法结束。否则,遍历与p项链的所有的边,将扩展出的到p的邻接点信息加入到优先队列。

    注意:当s = =t时需要计算K+1短路,以为st这条距离为0的路不能算在这K短路中,这时只需将K1后再求第K短路即可。

    题目:

    次短路 hdu3191  hdu1688 

    K短路 poj2499

     国界传送门:http://www.cnblogs.com/wally/archive/2013/04/16/3024490.html

     

    四、差分约束系统

     我已经做出总结。 传送门:http://www.cnblogs.com/Potato-lover/p/3959979.html

     

    五、DAG图上的单源最短路

    伪代码:

    1、初始化,入度为0的结点dist0,其他的结点的distINF

    2、对DAG进行拓扑排序,得到拓扑序列。

    3、按照拓扑序列遍历DAG的点,对于每个点u,遍历其所有的出边<u,v>,如果dist[v] > dist[u ] + Map[u][v],那么dist[v] > dist[u ] + Map[u][v]

    此方法可以处理负权边。

    题目: poj3249    

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 const int N = 100010, M =1100010, INF=0x3f3f3f3f;
     8 struct node
     9 {
    10     int to, w, next;
    11 };
    12 node edge[M];
    13 int ind[N], head[N], dist[N], que[N], cost[N];
    14 //Èë¶È
    15 int iq, ans;
    16 void topo(int n)
    17 {
    18     int i,k;
    19     iq=0;
    20     memset(que,0,sizeof(que));
    21     for(i=1;i<=n;i++)
    22         if(ind[i]==0) que[iq++]=i;
    23     for(i=0;i<iq;i++)
    24     {
    25         for(k=head[que[i]]; k!=-1; k=edge[k].next)
    26         {
    27             ind[edge[k].to]--;
    28             if(ind[edge[k].to]==0)
    29                 que[iq++]=edge[k].to;
    30         }
    31     }
    32 }
    33 void DAG(int n)
    34 {
    35     int i,k;
    36     ans=-INF;
    37     for(i=1;i<=n;i++) dist[i]=-INF;// -INF
    38     dist[n]=0;
    39     for(i=0;i<iq;i++)
    40     {
    41         int flag=1;
    42         for(k=head[que[i]];k!=-1;k=edge[k].next)
    43         {
    44             flag=0;
    45             if(dist[edge[k].to]<dist[que[i]] + edge[k].w)
    46                 dist[edge[k].to]=dist[que[i]] + edge[k].w;
    47         }
    48         if(flag) ans=max(ans,dist[que[i]]);
    49     }
    50 }
    51 void addedge(int i,int j,int k,int w)
    52 {
    53     edge[k].to=j;
    54     edge[k].w=w;
    55     edge[k].next=head[i];
    56     head[i]=k;
    57 }
    58 int main()
    59 {
    60     //freopen("test.txt","r",stdin);
    61     int n,m,i,j,k,t;
    62     while(scanf("%d%d",&n,&m)!=EOF)
    63     {
    64         memset(head,-1,sizeof(head));
    65         memset(ind,0,sizeof(ind));
    66         for(i=1;i<=n;i++) scanf("%d",&cost[i]);
    67         for(k=0;k<m;k++)
    68         {
    69             scanf("%d%d",&i,&j);
    70             ind[j]++;
    71             addedge(i,j,k,cost[j]);
    72         }
    73         for(i=1;i<=n;i++)
    74             if(ind[i]==0)
    75             {
    76                 ind[i]=1;
    77                 addedge(n+1,i,k++,cost[i]);
    78             }
    79         topo(n+1);
    80         DAG(n+1);
    81         printf("%d
    ",ans);
    82     }
    83     return 0;
    84 }
    View Code

     

    六、最小环

    Floyd求最小环

    Poj1734 Sightseeing trip

    Hdu1599

    传送门:http://www.cnblogs.com/Potato-lover/p/3954124.html

     

     

  • 相关阅读:
    数据库
    流式布局
    ScrollView简单用法
    ADB被占用解决办法
    安卓中shape中的属性大全
    sql语句replace into的用法
    debug
    大数据量数据库优化
    Gson解析后的数据存到本地数据库 耗时的问题
    数据同步异步加载handler Looper
  • 原文地址:https://www.cnblogs.com/Potato-lover/p/3999016.html
Copyright © 2011-2022 走看看