acwing算法基础之搜索与图论--朴素版dijkstra算法

目录

  • 1 基础知识
  • 2 模板
  • 3 工程化

1 基础知识

朴素版dijkstra算法的关键步骤:

  1. 初始化d[1]=0,d[2~n]=正无穷,例如0x3f3f3f3f。
  2. 用集合S来表示当前已被确定最小距离的结点们。
  3. 遍历每一个结点:找到不在S中的且距离结点1最近的结点,记为t。将结点t加入到集合S中。看看结点t可以走到哪儿,假设可以走到x,比较dist[x]和dist[t] + edge[t][x],如果前者大于后者,则用后者去更新前者。
  4. d[1~n],即为结点1到结点x的最短距离,x取1~n的值。

朴素版的dijkstra算法的核心是贪心,一直找最近的,最终的结果就是最近的。

2 模板

int g[N][N];  // 存储每条边
int dist[N];  // 存储1号点到每个点的最短距离
bool st[N];   // 存储每个点的最短路是否已经确定

// 求1号点到n号点的最短路,如果不存在则返回-1
int dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;

    for (int i = 0; i < n - 1; i ++ )
    {
        int t = -1;     // 在还未确定最短路的点中,寻找距离最小的点
        for (int j = 1; j <= n; j ++ )
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;

        // 用t更新其他点的距离
        for (int j = 1; j <= n; j ++ )
            dist[j] = min(dist[j], dist[t] + g[t][j]);

        st[t] = true;
    }

    if (dist[n] == 0x3f3f3f3f) return -1;
    return dist[n];
}

3 工程化

题目1:求结点1到结点n的最短路。

#include 
#include 

using namespace std;

const int N = 510;
int g[N][N];
int dist[N];
bool st[N];
int n, m;

int dijkstra() {
    memset(dist, 0x3f, sizeof dist);
    dist[1] = 0;
    
    for (int i = 0; i < n; ++i) {//遍历每一个结点,总共有n个结点,需要遍历n次
        int t = -1; //当前,距离结点1最近的结点且不在集合S中
        for (int j = 1; j <= n; ++j) {
            if (!st[j] && (t == -1 || dist[t] > dist[j])) {
                t = j;
            }
        }
        
        st[t] = true; //把t加入到集合S中
        for (int j = 1; j <= n; ++j) {//用t取更新剩余的结点
            if (!st[j]) {
                dist[j] = min(dist[j], dist[t] + g[t][j]);
            }
        }
        
    }
    
    if (dist[n] == 0x3f3f3f3f) return -1;
    else return dist[n];
}

int main() {
    cin >> n >> m;
    
    memset(g, 0x3f, sizeof g);
    int a, b, c;
    while (m--) {
        cin >> a >> b >> c;
        g[a][b] = min(g[a][b], c);
    }
    
    cout << dijkstra() << endl;
    
    return 0;
}

你可能感兴趣的:(Acwing,C++学习,算法,图论,数据结构)