zoukankan      html  css  js  c++  java
  • 最短路

    多源最短路

    Floyd

    时间复杂度:O(n3);空间复杂度:O(n2)
    1 for(int k=1;k<=n;k++)
    2 for(int i=1;i<=n;i++)
    3 for(int j=1;j<=m;j++)
    4 map[i][j]=min(map[i][j],map[i][k]+map[k][j];

     

    单源最短路

    SPFA

    初始化最短路径表;

    源点入队;

    取出队首点;

    枚举取出点的边;

    如果能松弛,就松弛,并把被松弛的点加入队列;

    如此循环直到队列为空。

    复制代码
     1 #include<cstdio>
     2 int n,m,s,v[10010];
     3 int a,b,c;
     4 int q[500010],head,tail;
     5 int h[10010],hs;
     6 struct edge{int s,n,v;}e[500010];
     7 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0; }
     8 int main(){
     9     scanf("%d%d%d",&n,&m,&s);
    10     for(int i=1;i<=n;i++) if(i!=s) v[i]=2147483647;
    11     for(int i=1;i<=m;i++){
    12         scanf("%d%d%d",&a,&b,&c);
    13         e[++hs]=(edge){b,h[a],c};
    14         h[a]=hs;
    15     }
    16     q[head++]=s;
    17     while(head>tail){
    18         a=q[tail++];
    19         for(int i=h[a];i;i=e[i].n){
    20             if(rel(v[e[i].s],v[a],e[i].v)){
    21                 q[head++]=e[i].s;
    22                 v[e[i].s]=v[a]+e[i].v;
    23             }
    24         }
    25     }
    26     for(int i=1;i<=n;i++) printf("%d ",v[i]);
    27     return 0;
    28 }
    复制代码

    适用于各种找单源最短路的题目;

    适用于负权图;

    可以根据判断节点的入队次数来判断图是否有负权回路。eg:泥泞的道路

    时间复杂度O(ke),理论复杂度高于Dijkstra,但有玄学加速。eg:【模板】单源最短路径*

    优化:

    SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾。

    LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。

    SLF 可使速度提高 15 ~ 20%;SLF + LLL 可提高约 50%。

    并未使用过,因为SPFA在时间上很优,一般不需要担心被卡常数。

    Dijkstra

    初始化最短路径表;

    源点标记;

    用源点的边松弛;

    寻找距离最短的未被标记的点;

    用这个点的边松弛;

    如此循环n-1次。

    复制代码
     1 #include<cstdio>
     2 int n,m,s,w[10010];
     3 int a,b,c;
     4 bool v[10010];
     5 int h[10010],hs;
     6 struct edge{int s,n,v;}e[500010];
     7 inline bool rel(long long x,long long y,long long z){return y+z<x?1:0;}
     8 int main(){
     9     scanf("%d%d%d",&n,&m,&s);
    10     for(int i=1;i<=n;i++) if(i!=s) w[i]=2147483647;
    11     for(int i=1;i<=m;i++){
    12         scanf("%d%d%d",&a,&b,&c);
    13         e[++hs]=(edge){b,h[a],c};
    14         h[a]=hs;
    15     }
    16     v[s]=1;
    17     for(int i=h[s];i;i=e[i].n) if(rel(w[e[i].s],0,e[i].v)) w[e[i].s]=e[i].v;
    18     for(int k=1;k<n;k++){
    19         a=2147483647;
    20         for(int i=1;i<=n;i++) if(!v[i]&&w[i]<a) a=w[i],b=i;
    21         v[b]=1;
    22         for(int i=h[b];i;i=e[i].n) if(rel(w[e[i].s],w[b],e[i].v)) w[e[i].s]=e[i].v+w[b];
    23     }
    24     for(int i=1;i<=n;i++) printf("%d ",w[i]);
    25     return 0;
    26 }
    复制代码

    !不能用于负权图。

    一般在OI中不太常用;

    时间复杂度O(n2),理论上平均比SPFA更快,实际上被完虐了。。。

    可以用堆优化,实现并不简单,然而优化效果也并不显然。

     

    Bellman-Ford

    时间复杂度O(ne),这个效率在OI中寸步难行,SPFA是其优化版。
    可以用于负权图,可以判断一个图中是否有负权回路。
     
  • 相关阅读:
    redis 基本操作-python 使用redis-手机验证接口-发送短信接口
    登录-注册页面修订
    10-29 课堂笔记
    git 协作开发
    git 常规使用
    luffy-city 基础环境搭建(至轮播图前后台交互实现)-步骤目录
    偏移分页-游标(加密)分页-自定义过滤器-第三方过滤器插件(django-filter)
    drf 大总结
    739. Daily Temperatures
    617. Merge Two Binary Trees
  • 原文地址:https://www.cnblogs.com/J-william/p/6821432.html
Copyright © 2011-2022 走看看