算法复习:最短路Dijkstra - Ford - Floyd

三世轮回 提交于 2020-02-23 11:22:48

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;
    }
};
leedcode 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];
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!