最短路dijkstra,SPFA

Posted on 2018-04-21 20:23  som_nico  阅读(209)  评论(0编辑  收藏  举报

Dijkstra算法

Dijkstra算法采用的是一种贪心的策略。

dijkstra不能有负权边

声明一个数组d来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T。

初始时,原点 s 的路径权重被赋为 0 (d[s] = 0)。若对于顶点 s 存在能直接到达的边(s,m),则把d[m]设为s到m的距离,同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大。初始时,集合T只有顶点s。 

然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到T中,OK,此时完成一个顶点, 
然后,我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短,如果是,那么就替换这些顶点在dis中的值。 
然后,又从dis中找出最小值,重复上述动作,直到T中包含了图的所有顶点。

 

 

dijkstra模板:

#include<stdio.h>
#include<string.h>
#define INFINITY 1000
int d[100];
int final[100];
int g[100][100];
int n;
void dijkstra(int s)
{
    int min, w, v, i, j;
    memset(final, 0, sizeof(final));
    for(v = 1; v <= n; v++)
        d[v] = g[s][v];
    final[s] = 1;
    d[s] = 0;
    for(i = 2; i <= n; i++)//这个点对应的一行的每一个点的最短都找出来
    {
        min = INFINITY;
        v = -1;
        for(w = 1; w <= n; w++) //在所有末标识的点中,选D值最小的点
        {
            if(!final[w] && d[w] < min)
            {
                v = w;
                min = d[w];
            }
        }

        if(v != -1)//如果v=-1表示现在在找的这个点没有与其他任何点有路径
        {
            final[v] = 1;

            for(w = 1; w <= n; w++)//找到最段路径后对应的与之相连的新点
                if((!final[w]) && (g[v][w] < INFINITY))
                {
                    if(d[w] > min + g[v][w])
                        d[w] = min + g[v][w];
                }
        }
    }
}
int main()
{
    int i, j;
    scanf("%d", &n);
    for(i = 1; i <= n; i++)
        for(j = 1; j <= n; j++)
            scanf("%d", &g[i][j]);
    dijkstra(1);
    for(i = 1; i <= n; i++)
        printf("%d ", d[i]);
    return 0;
}

 

 

 spfa算法

spfa可以有负权边

主要应用queue队列

有关spfa算法,这个博客写的很详细:最快最好用的——spfa算法

模板(这个是hdoj通畅工程续的ac代码):

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define inf 99999999
 4 #define maxn 210
 5 int maps[maxn][maxn];
 6 int visited[maxn], dis[maxn];
 7 int n, m;
 8 queue<int> q;
 9 int spfa(int s, int t)
10 {
11     for(int i = 0; i < n; i++)
12     {
13         dis[i] = inf;
14         visited[i] = 0;
15     }
16     while(!q.empty())
17         q.pop();
18     dis[s] = 0;
19     visited[s] = 1;
20     q.push(s);//起点入队
21 
22     while(!q.empty())
23     {
24         int temp = q.front();
25         q.pop();
26         visited[temp] = 0;
27         for(int i = 0; i < n; i++)
28         {
29             if(dis[i] > dis[temp] + maps[temp][i])
30             {
31                 dis[i] = dis[temp] + maps[temp][i];
32                 if(visited[i] == 0)
33                 {
34                     visited[i] = 1;
35                     q.push(i);//当前最短距离的点入队
36                 }
37             }
38 
39         }
40     }
41     if(dis[t] == inf)
42         return -1;
43     else
44         return dis[t];
45 }
46 int main()
47 {
48     int a, b, x, s, t, ans;
49     while(scanf("%d %d", &n, &m) != EOF)
50     {
51         for(int i = 0; i < n; i++)
52             for(int j = 0; j < n; j++)
53                 maps[i][j] = (i == j ? 0 : inf);
54         while(m--)
55         {
56             scanf("%d %d %d", &a, &b, &x);
57             if(x < maps[a][b])
58                 maps[a][b] = maps[b][a] = x;
59         }
60         scanf("%d %d", &s, &t);
61         ans = spfa(s, t);
62         printf("%d\n", ans);
63     }
64     return 0;
65 }

 

 

 

 

参考博客:最短路径问题---Dijkstra算法详解  最快最好用的——spfa算法