1 条题解

  • 0
    @ 2025-7-19 14:29:37

    朴素的 Dijkstra 算法

    • 初始化:除了起点之外,最短路都是无穷大,所有点都还没确定
    • 不停地去确定还没确定的点
      • 找到还没确定的点中最近的一个
      • 标记这个点已经确定了
      • 用这个点优化相邻的点
        • 尝试用 dis[u]+w 来优化 dis[v]
    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    // 因为会用到 INF+x,所以务必保证 INF+INF 不会溢出,否则就要特判
    const int INF = 1LL * 300'000 * 1'000'000'000;
    const int MAXN = 300000;
    const int MAXM = 300000;
    int n, m;
    vector<pair<int, int>> e[MAXN + 5];
    int dis[MAXN + 5];  // 起点到每个点的最短路
    bool vis[MAXN + 5]; // 是否确定下来了
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        // 输入存图
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            int u, v, w;
            cin >> u >> v >> w;
            e[u].push_back({v, w});
        }
        // Dijkstra 算法
        for (int i = 1; i <= n; i++)
        {
            dis[i] = INF;
            vis[i] = false;
        }
        dis[1] = 0;
        while (1)
        {
            int u = -1;
            for (int i = 1; i <= n; i++)
                if (vis[i] == false &&
                    (u == -1 || dis[i] < dis[u]))
                    u = i;
            if (u == -1)
                break;
            vis[u] = true;
            for (int i = 0; i < e[u].size(); i++)
            {
                int v = e[u][i].first;
                int w = e[u][i].second;
                dis[v] = min(dis[v], dis[u] + w);
            }
        }
        for (int i = 1; i <= n; i++)
            if (dis[i] == INF)
                cout << -1 << " ";
            else
                cout << dis[i] << " ";
        return 0;
    }
    

    优先队列优化的 Dijkstra 算法

    • 初始化:除了起点之外,最短路都是无穷大,所有点都还没确定
    • 把起点放入优先队列
    • 只要优先队列还有东西,就继续优化
      • 取出当前最近的
      • 如果这个点已经被确定了,就跳过这个点
      • 如果没有确定,这个点可以确定下来了,不可能被优化了
      • 用这个点优化相邻的点
        • 尝试用 dis[u]+w 来优化 dis[v]
    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    // 因为会用到 INF+x,所以务必保证 INF+INF 不会溢出
    // 实际上也可以用 -1 表示无法到达,然后特判 -1 即可
    const int INF = 1LL * 300'000 * 1'000'000'000;
    const int MAXN = 300000;
    const int MAXM = 300000;
    int n, m;
    vector<pair<int, int>> e[MAXN + 5];
    int dis[MAXN + 5];  // 起点到每个点的最短路
    bool vis[MAXN + 5]; // 是否确定下来了
    // 存 <-dis[i],i> 来保证每次都能拿出来最近的点
    priority_queue<pair<int, int>> q;
    signed main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);
        // 输入存图
        cin >> n >> m;
        for (int i = 1; i <= m; i++)
        {
            int u, v, w;
            cin >> u >> v >> w;
            e[u].push_back({v, w});
        }
        // Dijkstra 算法
        for (int i = 1; i <= n; i++)
        {
            dis[i] = INF;
            vis[i] = false;
        }
        dis[1] = 0;
        q.push({-dis[1], 1});
        while (!q.empty())
        {
            int u = q.top().second;
            q.pop();
            if (vis[u])
                continue;
            vis[u] = true;
            for (int i = 0; i < e[u].size(); i++)
            {
                int v = e[u][i].first;
                int w = e[u][i].second;
                if (dis[u] + w < dis[v])
                {
                    dis[v] = dis[u] + w;
                    q.push({-dis[v], v});
                }
            }
        }
        
        for (int i = 1; i <= n; i++)
            if (dis[i] == INF)
                cout << -1 << " ";
            else
                cout << dis[i] << " ";
        return 0;
    }
    
    • 1

    信息

    ID
    8595
    时间
    2000ms
    内存
    512MiB
    难度
    3
    标签
    (无)
    递交数
    11
    已通过
    4
    上传者