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

    背景:

    只是想来备份一下最近的代码,顺便总结一下三种最短路算法的应用。

    基础代码:

    dijkstra:

     1 struct nd{int d,u; bool operator < (const nd &a)const{return d>a.d;}};
     2 int d[maxn]; bool vis[maxn]; priority_queue<nd>q;
     3 void dijkstra(int s){
     4     inc(i,1,n)d[i]=INF; d[s]=0; q.push((nd){0,s});
     5     while(!q.empty()){
     6         int x; while(!q.empty()&&vis[x=q.top().u])q.pop(); if(vis[x])break; vis[x]=1;
     7         for(int i=g[x];i;i=es[i].n)if(d[es[i].t]>d[x]+es[i].w){
     8             d[es[i].t]=d[x]+es[i].w; q.push((nd){d[es[i].t],es[i].t});
     9         }
    10     }
    11 }

    spfa(bfs+slf):

     1 ll d[maxn]; bool inq[maxn]; deque<int>q;
     2 ll spfa(){
     3     inc(i,1,n)d[i]=INF; d[1]=0; inq[1]=1; q.push_back(1);
     4     while(!q.empty()){
     5         int x=q.front(); q.pop_front(); inq[x]=0;
     6         for(int i=g[x];i;i=es[i].n)if(d[es[i].t]>d[x]+es[i].w){
     7             d[es[i].t]=d[x]+es[i].w;
     8             if(!inq[es[i].t]){
     9                 if(!q.empty()&&d[es[i].t]<d[q.front()])q.push_front(es[i].t);else q.push_back(es[i].t);
    10                 inq[es[i].t]=1;
    11             }
    12         }
    13     }
    14     return d[n];
    15 }

    spfa(dfs):

     1 bool ins[maxn],f; double d[maxn];
     2 void dfs(int x){
     3     ins[x]=1;
     4     for(int i=g[x];i;i=es[i].n){
     5         if(f)return;
     6         if(d[es[i].t]>d[x]+es[i].w){
     7             if(ins[es[i].t]){f=1; return;} d[es[i].t]=d[x]+es[i].w; dfs(es[i].t);
     8         }
     9     }
    10     ins[x]=0;
    11 }
    12 bool spfa(){
    13     memset(ins,0,sizeof(ins)); memset(d,0,sizeof(d)); f=0;
    14     inc(i,1,n){dfs(i); if(f)return 0;} return 1;
    15 }

    floyd:

     1 inc(k,1,n)inc(i,1,n)inc(j,1,n)if(map[i][k]+map[k][j]<map[i][j])map[i][j]=map[i][k]+map[k][j]; 

    比较:

    dijkstra:

    本算法的优点就是快,没有什么一定需要其解决的问题,且只能处理正权边及求最短路(不能求最长路)。复杂度为O(mlog2n)不过常数会稍大。

    spfa:

    优点是可以处理负权边以及判负环,当不用判负环时bfs+slf(双端队列优化)的最坏复杂度是O(nm),但是常数很小,有时快过dijkstra。当需要判负环时bfs+slf复杂度经常会达到最坏复杂度,这时候用dfs写法会明显快很多,因为在不连通图中判负环需要每个点都作为源点跑一次。

    floyd:

    优点是短,可以用一行求出两两点的最短路,复杂度O(n3)且常数很小。

    常见模型:

    差分约束系统

    n个数,知道他们两两之间形如ai-aj≥c,ai-aj≤c的关系,求n个数最小/最大是多少。解法:如果是求最大值,则将所有限制条件转化为为≤,将得到的i和j连边,权值为c并跑最短路,因为得到的是满足条件的最大值;如果是求最小值,则将所有限制条件设定为≥,将得到的i和j连边,权值为c并跑最长路,因为得到的是满足条件的最小值。

    01分数规划:

    n点m边有向图,点有点权,边有边权,从某点出发,走一些路使得经过的点权和除以(浮点数除法)边权和最大或最小,求这个小数(保留两位)。解法:假设需要所求小数最大,那么二分这个数,然后将所有边的边权改为分母(需要最小化的部分)*二分的数-分子(需要最大化的部分),然后判负环。如果有,说明解合法,否则解不合法。最后把下界输出。如果需要所求小数最小,则把边权改为分子(需要最大化的部分)-分母(需要最小化的部分)*二分的数,同时改变范围缩小的方向。

    倍增floyd:

    从s到t,要求刚好经过k条边,求最短路。解法:把用floyd的方式对两个邻接矩阵进行合并定义成一个运算,则答案为初始矩阵与自己做k次运算得到的结果。而该运算符合结合律,故可以用类似矩阵快速幂的方法刚好做log2k次运算。

  • 相关阅读:
    Java笔记06
    Kubernetes V1.16.2部署Dashboard V2.0(beta5)
    安装Kubernetes V1.16.2
    Spring Cloud Stream 进行服务之间的通讯
    通过总线机制实现自动刷新客户端配置(Consul,Spring Cloud Config,Spring Cloud Bus)
    手动刷新客户端配置内容(Spring Cloud Config)
    创建客户端项目并读取服务化的配置中心(Consul + Spring Cloud Config)
    创建配置中心服务端(Spring Cloud Config)
    Consul集群加入网关服务(Spring Cloud Gateway)
    Consul集群Server+Client模式
  • 原文地址:https://www.cnblogs.com/YuanZiming/p/6058943.html
Copyright © 2011-2022 走看看