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

    ----------------------------------------第一次写博客的心情分割线---------------------------------------------

    啥是最短路QAQ???

    最短路:用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。——百度百科

    从一点到其他任一点有多条路径,问哪一种走法最省时省力,就是最短路问题。

    常用的求最短路的算法有三种:Dijkstra算法,Floyd算法,SPFA算法

    一、Dijkstra算法

    \\如果我是DJ你會愛我嗎你會愛我嗎 呸 >>博主是個fzl(=v=)\\

    算法思想:贪心

      从起点开始每次扩展一个距离最短的点,再以该点为中心,更新起点到其他所有点的距离

      距离最短的点:可以用优先队列实现

    试用范围:不带负边权的有向图或无向图

    priority_queue< pair<int,int> >q;
    void dijkstra(int s)//s:起点 
    {
        memset(dis,0x3f,sizeof(dis));//初始化dis[i]为正无穷 
        memset(v,0,sizeof(v));//标记为未访问过
        d[s]=0; 
        q.push(make_pair(0,1));
        while(q.size())//此处也可以写成while(!q.empty())
        {
            int x=q.top().second;//取出堆顶 
            q.pop();
            if(v[x])
                continue;//选择一个 未标记的点
            v[x]=1;//结点标记
            for(int i=head[x];i;i=nex[i])//邻接表 扫描出边
            {
                int y=ver[i],z=edge[i];
                if(d[y]>d[x]+z)
                {
                    d[y]=d[x]+z;
                    q.push(make_pair(-d[y],y));
                }
            }
        }
    }

    关于代码最后一行"q.push(make_pair(-d[y],y))"

    可以发现这里插入的是-d[y]而不是d[y]

    因为优先队列默认大根堆 而插入dis的相反数恰好可以改写这个性质

    二、Floyd算法

    算法思想:DP

      转移方程:d[i][j]=min(d[i][j],d[i][k]+d[k][i])

    适用范围:没有负环的图

    for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
             for(int j=1;j<=n;j++)
             {
                 if(i!=j&&i!=k&&j!=k)
                 d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
             }
        }
    }

    运用了三层循环 因此这个代码的时间复杂度为n^3

    注意 d数组要初始化为极大值哦!

    三、SPFA算法

    基本算法:

      ①设立队列

      ②每次取出队首,标记该点出队,并从该点对与该点相连的点进行松弛操作,如果松弛成功,更新

      ③若松弛成功且新的点不在队列中,新结点入队

      ④循环②③直到队列为空

    #include<queue>
    using namespace std; 
    void SPFA()
    {
        queue <int> q;
        memset(d,0x3f,sizeof(d));
        memset(v,0,sizeof(v));
        d[1]=0;
        v[1]=1;
        q.push(1);
        while(!q.empty())
        {
            int x=q.front();//取出队头
            q.pop();//pop!!!
            v[x]=0;
            for(int i=head[x];i;i=nex[i])
            {
                int y=ver[i],z=edge[i];
                if(d[y]>d[x]+z)
                {
                    d[y]=d[x]+z;//不断更新 
                    if(!v[y])
                        q.push(y),v[y]=1;
                }
            }
        }
    }

    每次入队需要先满足三角不等式d[y]>d[x]+z

    一个结点可能多次出入队列 最终使所有点收敛到全部满足三角不等式的状态

    该算法的时间复杂度会小于O(n*m)

  • 相关阅读:
    Restful接口传入多参数
    map转换成JSON的3种方式
    项目打包后执行start.sh提示“no such file or directory”解决办法,linux中给文件增加权限
    如何将一个a表a1字段与b表b1字段的笛卡尔积插入到e表中
    get、set方法的取代注释之lombok插件
    推荐 33 个 IDEA 最牛配置转(Java技术栈)
    mysql-----group by 对多个字段进行分组
    mysql获取某段时间内每一天的统计数据
    发票流水号生成方式
    postman之post请求传参
  • 原文地址:https://www.cnblogs.com/WJill/p/11206980.html
Copyright © 2011-2022 走看看