【问题标题】:Is there any bug in this dijkstra algorithm implementation?这个 dijkstra 算法实现中是否有任何错误?
【发布时间】:2020-07-03 09:13:48
【问题描述】:

我刚刚学习了 Dijkstra 的算法并解决了一些问题,我正在尝试解决这个 http://codeforces.com/problemset/problem/20/C 问题,但我在测试用例 31 中得到了错误的答案。我不明白为什么它会得到错误的答案。首先,它在测试用例 31 上超出了内存限制。但是当我将 int 更改为 d[] 数组的 long long 时,它得到了错误的答案。请让我知道为什么它会得到错误的答案。

我的代码:

#include <bits/stdc++.h>

using namespace std;

typedef struct data Data;

struct data{
    long long int city,dis;
    bool operator < (const data & p) const{
        return dis > p.dis;
    }
};

#define tr(niloy,it) for(auto it = niloy.rbegin(); it != niloy.rend(); it++)

void dijkstra(const vector <long long int>  edge[],const vector <long long int>  cost[], int source, int destination,int n,int m)
{
    long long int d[n];
    bool nodes[n];
    vector <int> parent(n,-1);
    for(int i = 0; i < n; i++){
        d[i] = INT_MAX;
        parent[i] = -1;
        nodes[i] = false;
    }
    priority_queue <Data> p;
    Data u,v;
    u.city = 0;
    u.dis = 0;
    p.push(u);
    d[source] = 0;
    while(!p.empty()){
        u = p.top();
        p.pop();
        long long int ucost = d[u.city];
        if(u.city == destination)break;
        if(nodes[u.city])continue;
        nodes[u.city] = true;
        //cout << edge[u.city].size() << endl;
        for(int i = 0; i < edge[u.city].size(); i++){
            v.dis = ucost + cost[u.city][i];
            v.city = edge[u.city][i];
            if(d[v.city] > v.dis){
                ///cout << v.city << " " << u.city << endl;
                parent[v.city] = u.city;
                d[v.city] = v.dis;
                p.push(v);
            }
        }
    }
    vector<int> niloy;
    ///cout << d[destination] << endl;
    if(parent[destination] != -1){
        niloy.push_back(n);
        while(destination != 0){
            niloy.push_back(parent[destination]+1);
            destination = parent[destination];
        }
        tr(niloy,it)cout << *it << " " ;
    }else{
        ///cout << d[destination] << endl;
        cout << -1 << endl;
    }

}

int main()
{
    int n,m;
    cin>> n >> m;
    vector <long long int> edge[n],cost[n];

    int a,b,c;

    for(int i = 0; i < m; i++){
        cin >> a >> b >> c;
        if(a == b)continue;
        edge[a-1].push_back(b-1);
        cost[a-1].push_back(c);
        edge[b-1].push_back(a-1);
        cost[b-1].push_back(c);
    }
    //cout << edge[0][0] << endl;
    dijkstra(edge,cost,0,n-1,n,m);

    return 0;
}

【问题讨论】:

  • “这个实现中是否有错误”+“我得到错误的答案”=是的,你有一个错误。这个网站有提供失败的测试用例吗?
  • 另外,C++ 没有variable-length arrays,请改用std::vector
  • 最后,请不要将在线竞赛/评委网站用作学习资源,因为它们不是。请改用a couple of good books,或上课。
  • long long int d[n]; -- 这行和其他类似的行是不是有效的 C++。 C++ 中的数组的大小必须由编译时常量而不是运行时值来表示。如果您的整个程序因n 很大而崩溃,我不会感到惊讶,因为程序会耗尽堆栈内存。您应该将std::vector 用于动态数组,而不是您现在使用的假 VLA 数组。你已经在使用矢量了,所以你也应该在这里使用它们。

标签: c++ dijkstra


【解决方案1】:

算法实现对我来说看起来是正确的,唯一看起来错误的是这一行:

d[i] = INT_MAX;
如果编译器使用 32 位整数,

INT_MAX 将为 2^32(接近 10^9),而如果您有线性图,则最佳解决方案的最大可能实际长度可能会更多如:1 -> 2 -> 3 -> ... -> n 并且每条边的长度为 10^6。在这种情况下,最短路径将接近 10^11,大于 INT_MAX,这意味着 d 数组的初始值并不像 dijkstra 算法所要求的那样真正“无限”。

将初始值更改为更大的数字应该可以解决此问题(10^12 应该足够了,但您也可以使用 LLONG_MAX):

d[i] = 1000000000000; // 10^12

【讨论】:

  • 另外,我同意问题 cmets 中的建议,尽可能使用std::vector。例如这里的 edgecost 可以是向量的向量:std::vector&lt;std::vector&lt;long long int&gt;&gt;,这样你就可以通过引用传递它们并使用.size() 函数获取大小,所以你赢了'也不需要传递 nm
猜你喜欢
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 2016-02-27
  • 1970-01-01
  • 1970-01-01
  • 2012-07-01
  • 1970-01-01
相关资源
最近更新 更多