zoukankan      html  css  js  c++  java
  • 算法复习:最短路Dijkstra

    Dijkstra算法适用范围是单源最短路,有向图或者无向图,不能处理负权值

    Floyd算法适用多源最短路,有向图或者无向图,可以处理负权值但是不能处理负权回路

    Ford 算法最短路,可以处理负权值,能检测负权回路

    Leetcode 743. 网络延迟时间

    一、先用Dijkstra算法解,输入是vector要转存一下,另外找的是最后一个传播到的节点所用时间

    #define max 999999
    #define CLR(donser,value) memset(donser,value,sizeof(donser))
    class Solution {
    public:
        int networkDelayTime(vector<vector<int>>& times, int N, int K) 
        {
            int dis[N+1],map[N+1][N+1];
            CLR(dis,max);
            bool visit[N+1];
            CLR (visit,false);
            for(int i=1;i<=N;i++)//先初始化map
                for(int j=1;j<=N;j++)
                    map[i][j]=max;
            for(int i=0;i<times.size();i++)//把边转存到map
                map[times[i][0]][times[i][1]]=times[i][2];
            for(int i=1;i<=N;i++)//和起点直接相连的边
            {
                if(i==K)
                    dis[i]=0;
                else
                    dis[i]=map[K][i];
            }
            visit[K]=true;//起点做标记
            for(int i=1;i<=N;i++)//循环N次
            {
                int min=max,k;
                for(int j=1;j<=N;j++)//找未加入visit的点所连最小边
                {
                    if(!visit[j]&&min>dis[j])
                        min=dis[k=j];//k记录取到最小值时的下标
                }
                if(min==max)//不存在没加入的边了
                    break;
                visit[k]=true;
                for(int j=1;j<=N;j++)//给没有加入的边更新权值
                {
                    if(!visit[j]&&dis[j]>dis[k]+map[k][j])//新加入了K,把与K相连的边加入
                        dis[j]=dis[k]+map[k][j];
                }
            }
            int find=0;
            for(int i=1;i<=N;i++)
                if(dis[i]>find)
                    find=dis[i];
            if(find==max)
                return -1;
            else
                return find;
        }
    };
    leetcode 743

    另外,Dijkstra算法模板:

    #define N 101
    #define max 999999
    #define CLR(arr,what) memset(arr,what,sizeof(arr))
    int nodenum,edgenum;
    int map[N][N],dis[N];
    bool visit[N];
    int Dijkstra(int src,int des)//输入开始点和结束点
    {
        int temp,k;
        CLR(visit,false);
        for(int i=0;i<=nodenum;i++)//先把和开始点直接相连的边找出来
        {
            if(i==src)
                dis[i]=0;//dis[i]存连入i的边,起始点赋0
            else
                dis[i]=map[src][i];
        }
        visit[src]=true;//起始点做标记
        dis[src]=0;
        for(int i=1;i<=nodenum;i++)//做i次循环
        {
            temp=max;
            for(int j=1;j<=nodenum;j++)//寻找没有加入visit的节点中权值最小的
            {
                if(!visit[j]&&temp>dis[j])
                    temp=dis[k=j];
            }
            if(temp==max)//不存在没有加入的边时结束
                break;
            visit[k]=true;//访问标记
            for(int j=1;j<=nodenum;j++)//加入k点以后更新和k相连的边
            {
                if(!visit[j]&&dis[j]>dis[k]+map[k][j])
                    dis[j]=dis[k]+map[k][j];
            }
        }
        return dis[des];
    }
    DJ模板

    Leetcode 743. 网络延迟时间

    二、改用Floyd算法解决,floyd三层循环更新二维表,本质上就是借助一个中间点实现节点更新,时间复杂度:O(N^3)

    #define max 999999
    class Solution {
    public:
        int networkDelayTime(vector<vector<int>>& times, int N, int K) 
        {
            int map[N+1][N+1];
            for(int i=1;i<=N;i++)//先初始化map 对角线0,其他max
                for(int j=1;j<=N;j++)
                    map[i][j]=(i==j?0:max);
            for(int i=0;i<times.size();i++)//把边转存到map
                map[times[i][0]][times[i][1]]=times[i][2];
            for(int k=1;k<=N;k++)
            {
                int lable=0;
                for(int i=1;i<=N;i++)
                    for(int j=1;j<=N;j++)
                        if(map[i][k]<max&&map[k][j]<max&&map[i][j]>map[i][k]+map[k][j])
                            map[i][j]=map[i][k]+map[k][j];
            }
            int find=0;
            for(int i=1;i<=N;i++)
            {
                if(map[K][i]>find)
                    find=map[K][i];
            }  
            if(find==max)
                return -1;
            else
                return find;
        }
    };
    leetcode 743

    Floyd核心代码:

    for(int k=1;k<=N;k++)
      for(int i=1;i<=N;i++)
        for(int j=1;j<=N;j++)
          if(map[i][k]<max&&map[k][j]<max&&map[i][j]>map[i][k]+map[k][j])
            map[i][j]=map[i][k]+map[k][j];

    Leetcode 743. 网络延迟时间

    三、改用Bellman-Ford算法,最外层循环节点数-1次,内层循环遍历所有的边值更新权值表,时间复杂度O(NM)

    l#define max 999999
    #define CLR(donser,value) memset(donser,value,sizeof(donser))
    class Solution {
    public:
        int networkDelayTime(vector<vector<int>>& times, int N, int K) 
        {
            int dis[N+1];
            CLR(dis,max);
            dis[K]=0;
            for(int k=1;k<=N-1;k++)//第一个点是确定的,循环次数-1
            {
                for(int i=0;i<times.size();i++)//遍历所有边
                {
                    if(dis[times[i][0]]<max&&times[i][2]<max&&dis[times[i][0]]+times[i][2]<dis[times[i][1]])
                        dis[times[i][1]]=dis[times[i][0]]+times[i][2];
                }
            }
            int find=0;
            for(int i=1;i<=N;i++)
                if(dis[i]>find)
                    find=dis[i];
            if(find>=max)
                return -1;
            else
                return find;
        }
    };
    leetcode 743

    Ford核心代码:

    for(int k = 1; k <= n-1; k++) //进行n-1轮松弛
        for(int i = 1; i <= m; i++) //枚举每一条边
            if(dis[u[i]] != INF && w[i] != INF && dis[u[i]] + w[i] < dis[v[i]]) //尝试对每一条边进行松弛
                dis[v[i]] = dis[u[i]] + w[i];
  • 相关阅读:
    keras系列︱迁移学习:利用InceptionV3进行fine-tuning及预测、完美案例(五)
    keras系列︱人脸表情分类与识别:opencv人脸检测+Keras情绪分类(四)
    keras系列︱图像多分类训练与利用bottleneck features进行微调(三)
    keras系列︱Application中五款已训练模型、VGG16框架(Sequential式、Model式)解读(二)
    将C++资源文件读取出来
    windows驱动程序中的预处理含义
    win10网上邻居看不到别的共享电脑怎么样办
    #pragma alloc_text 与 ALLOC_PRAGMA
    IoAllocateMdl,MmProbeAndLockPages的用法
    Composer三步曲:安装、使用、发布
  • 原文地址:https://www.cnblogs.com/dzzy/p/12348705.html
Copyright © 2011-2022 走看看