Dijkstra算法(最短路)

Dijkstra算法是单源最短路径算法;利用的是贪心思想,每次选择当前的最靠近源点的顶点确定为最短路径(所以Dijkstra算法需要满足的是所有边的权值都为正值,所以Dijkstra不能处理负边权问题)。

算法思路:

1. 将所有点分为两部分:已知最短路径顶点和未知最短路径顶点,先将源点加入已知最短路径,利用book[]存储。

2. 初始化各顶点的最短路径,有源点直接相连的点设置为边的权值,没有直接相连的点设置为无穷大;

3. 在所有未知最短路径的顶点中寻找距离最小的将其确定为最短路径,并对这点的所有出边进行松弛操作;

4. 重复3操作,直到所有点确定最短路径;

代码:

#include <string.h>
#include<iostream>
#include<vector>
#include<queue>
#define _Max 200020
#define INF 1<<30
using namespace std;
int main()
{
    int e[10][10],dis[_Max],book[_Max];
    int n,m,s,t,w;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j) e[i][j]=0;
            else e[i][j]=INF;
        }
    }
    cin>>n>>m;
    for(int i=0;i<m;i++){
        cin>>s>>t>>w;
        e[s][t]=w;
    }
    //初始化1号顶点到其他顶点的距离
    for(int i=1;i<=n;i++){
        dis[i]=e[1][i];
    }
    //初始化book数组,1表示已求得最短路径,0表示未知最短路径
    for(int i=1;i<=n;i++){
        book[i]=0;
    }
    book[1]=1;

    int min,u;
    //dijkstra算法核心语句
    for(int i=1;i<n;i++){//每次可以求得一个顶点的最短路径,通过n-1轮即可全部求出
        //找到距离源点最远的未知最短路径的点,则这点可以确定为最短路径
        min=INF;
        for(int j=1;j<=n;j++){
            if(book[j]!=1&&dis[j]<min){
                min=dis[j];
                u=j;
            }
        }
        book[u]=1;
        for(int k=1;k<=n;k++){
            if(e[u][k]<INF&&book[k]==0){
                if(dis[k]>dis[u]+e[u][k])
                    dis[k]=dis[u]+e[u][k];
            }
        }
    }
    for(int i=0;i<=n;i++){
        cout<<dis[i]<<endl;
    }


    return 0;
}

输入示例:

6 9
1 2 1

1 3 12

2 3 9

2 4 3

3 5 5

4 3 4 

4 5 13

4 6 15

5 6 4

输出示例:

0

1

8

4

13

17

Dijstra算法为什么不能处理负边权问题?

例如:有三条边 1 3 8, 1 2 9, 2 3 -2;

由于Dijstra算法贪心思想,会先确定3号顶点的最短路径为8,但是因为有负边1-2-3的路径权值为7,所以当有负边是Dijstra算法不再适用;

猜你喜欢

转载自www.cnblogs.com/zdl2234/p/10360613.html