为什么此Dijkstra算法不适用于此特定输入?

麻雀2

我已经实现了Dijkstra的算法但是,当输入以下内容时,它将不起作用:

1
6 7
1 2 5
2 3 2
3 4 3
1 4 9
4 5 2
5 6 3
1 6 2
1

我在调试模式下运行它,以了解出了什么问题。看来节点5没有插入单元中。我不知道为什么。

这里的代码:

#include<iostream>
#include<vector>
#include<list>
#include <limits>
#include <algorithm>
#include <queue>
#include <set>
#include <stack>
using namespace std;

struct compare
{
    bool operator()(pair<int, int> a, pair<int, int> b) const
    {
        return a.second < b.second;
    }

};

void printResults(vector<int> vec, int starting)
{
    for (int i = 1; i < vec.size(); i++)
    {
        if (vec[i] == numeric_limits<int>::max() && i != starting)
        {
            cout << -1 << " ";
        }
        else if (i != starting)
        {
            cout << vec[i] << " ";
        }
    }

}
void djkstra(vector<vector<pair<int, int>>>&vec, int starting, int number_of_vertices)
{
    int max = numeric_limits<int>::max();
    set <pair<int, int>,compare> queue;
    vector<bool> visited(number_of_vertices + 1, false);
    vector<int> distances(number_of_vertices + 1, max);
    vector<int> parents(number_of_vertices + 1, -1);
    queue.insert(make_pair(starting, 0));
    distances[starting] = 0;
    for (int i = 0; i<number_of_vertices-1; i++)
    {
        pair<int, int> minElem = *queue.begin(); //take min elem
        queue.erase(minElem);
        vector<pair<int, int>> adjacents = vec[minElem.first];//take neighbours
        for (int j = 0; j<adjacents.size(); j++)
        {
            pair<int, int> node = adjacents[j];
            if (!visited[node.first])
            {
                if (distances[node.first]> distances[minElem.first] + node.second) //if we have found smaller distance
                {

                    if (queue.find(make_pair(node.first, distances[node.first])) != queue.end())
                    {
                        queue.erase(make_pair(node.first, distances[node.first]));
                        queue.insert(make_pair(node.first, distances[minElem.first] + node.second));

                    }
                    else
                    {
                        queue.insert(make_pair(node.first, distances[minElem.first] + node.second));
                        cout<<distances[minElem.first] + node.second<<endl;

                    }

                    distances[node.first] = distances[minElem.first] + node.second;
                }

            }

        }
        visited[minElem.first] = true;

    }
    printResults(distances,starting);

}

int main()
{
    int test;
    cin >> test;
    for (int i = 0; i < test; i++)
    {
        int nodes, edges;
        cin >> nodes >> edges;
        vector<vector<pair<int, int>>> vec(nodes + 1);
        for (int j = 0; j < edges; j++)
        {
            int src, des, weight;
            cin >> src >> des >> weight;
            vec[src].push_back(make_pair(des, weight));
            vec[des].push_back(make_pair(src, weight));

        }

        int starting;
        cin >> starting;
        djkstra(vec, starting, nodes);

    }

    system("pause");

    return 0;
}
看到

所以,经过努力,以化妆的感觉你的代码有问题,我根据在到达一个干净重新写维基百科伪代码

认为(因为您仍然从未显示过您认为错误的输出),您的主要错误只是使用了set<>

Bugged Version

#include <algorithm>
#include <iostream>
#include <limits>
#include <list>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <cassert>

using Vertex  = unsigned;
using Weight  = double;

struct OutEdge {
    Vertex node;
    Weight weight;
    bool operator<(OutEdge const& o) const { return weight < o.weight; }
};

using OutEdges     = std::vector<OutEdge>;
using AdjList      = std::vector<OutEdges>;
using Distances    = std::vector<Weight>;
using Predecessors = std::vector<Vertex>;

static Weight const INFINITY = std::numeric_limits<Weight>::max();
static Vertex const UNDEFINED {-1u};

using namespace std;

void print_graph(AdjList const& graph) {
    for (Vertex v = 1; v < graph.size(); v++) {
        std::cout << v << " -";
        for (auto& adj : graph[v])
            std::cout << " " << adj.node << "(" << adj.weight << ")";
        std::cout << "\n";
    }
}

void printResults(Distances const& dist, Vertex starting) {
    for (Vertex v = 0; v < dist.size(); v++) {
        std::cout << starting << " -> " << v << ": ";
        if (dist[v] == INFINITY && v != starting) {
            cout << -1 << " ";
        } else { // if (v != starting) {
            cout << dist[v] << " ";
        }
        std::cout << "\n";
    }
}

Distances dijkstra(AdjList const& graph, Vertex source) {
    std::set<OutEdge> Q;

    vector<bool> visited(graph.size(), false);
    Distances    dist(graph.size(), INFINITY);  // Unkown distance from source
    Predecessors prev(graph.size(), UNDEFINED); // Previous node in optimal path from source

    dist[source] = 0; // Distance from source to source

    for (Vertex v = 1; v < graph.size(); v++)
        Q.insert({v, dist[v]});

    while (!Q.empty()) {
        Vertex u = Q.begin()->node;
        visited[u] = true;
        Q.erase(Q.begin());

        for (auto& v : graph[u]) { // for each neighbour
            if (visited[v.node]) // where v is still in Q.
                continue;

            Weight alt = dist[u] + v.weight;

            if (alt < dist[v.node]) // A short path to v has been found
            {
                dist[v.node] = alt;
                prev[v.node] = u;

                // update prio
                auto it = std::find_if(Q.begin(), Q.end(), [&](auto& oe) { return oe.node == v.node; });
                if (it != Q.end()) {
                    Q.erase(it);
                    Q.insert({v.node, alt});
                }
            }
        }
    }

    return dist;
}

int main() {
    size_t test;
    cin >> test;
    for (size_t i = 0; i < test; i++) {
        size_t nodes, edges;
        cin >> nodes >> edges;
        nodes += 1; // hack to avoid converting ids to base-0

        AdjList adj(nodes);
        for (size_t j = 0; j < edges; j++) {
            Vertex src, des;
            Weight weight;

            cin >> src >> des >> weight;
            assert(weight>=0);

            adj[src].push_back({des, weight});
            adj[des].push_back({src, weight});
        }

        print_graph(adj);

        Vertex starting;
        cin >> starting;
        auto d = dijkstra(adj, starting);
        printResults(d, starting);
    }
}

将结果打印为:

1 -> 0: -1 
1 -> 1: 0 
1 -> 2: 5 
1 -> 3: 7 
1 -> 4: 9 
1 -> 5: -1 
1 -> 6: 2 

注意您在djkstra[sic]中至少还有一个错误

for (int i = 0; i<number_of_vertices-1; i++)

-1似乎是完全错误的(如果有的话,+1尽管+1散布了所有代码,这是一个巨大的代码味道,但“应该”已经存在了。请参阅如何在我的版本中解决该问题。

说明

std::set<>使用唯一元素对容器建模。在这种情况下,重量是等效属性,因此,所有具有相同重量的元素都是等效的。从一开始,队列将最多包含2个元素:1个起始顶点(距离0)和所有其他顶点以相同距离(INFINITY;或max在您的版本中)播种的其他顶点中的1个

这将沉没您的算法,因为永远不会访问许多节点(一旦队列为空,算法就会停止)。

解决方法是5个字母s/set/multiset/::

Fixed Version

印刷品:

1 -> 0: -1 
1 -> 1: 0 
1 -> 2: 5 
1 -> 3: 7 
1 -> 4: 7 
1 -> 5: 5 
1 -> 6: 2 

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

为什么此类型推断不适用于此Lambda表达式方案?

为什么Dijkstra的算法不适用于负负边缘?

为什么ExtractMpegFramesTest不适用于旋转的输入文件?

为什么从{3}更改为{4}不适用于此正则表达式?

为什么此代码不适用于特定类型的数据?

为什么height:auto不适用于此图像?

为什么ES6 ComputedPropertyName不适用于此React JS代码?

为什么输入模式属性不适用于数字?

为什么$别名不适用于此jQuery函数

为什么此仅用于数字输入的功能实际上不适用于输入类型:数字?

为什么Mysql order by不适用于此查询

为什么此代码不适用于svg元素?

为什么此脚本仅适用于此列表中的列表项之一?

为什么预先输入不适用于此MVC5应用程序?

为什么此解决方案不适用于硬币找零算法?

Dijkstra算法实现-代码不适用于较大的输入

Karatsuba算法适用于小数而不适用于大数,看不出为什么

为什么我的Javascript警报不适用于此自定义WordPress插件?

为什么此过渡属性不适用于 css?

为什么 Scrapy 不适用于此页面?

为什么 numba 不适用于此嵌套函数?

为什么单选按钮不适用于此代码?

为什么 CORS 不适用于此配置?

为什么此查询不适用于指定的日期?

为什么验证不适用于此功能?

为什么“$(document).ready(function()”不适用于此脚本?

为什么scrapy shell 不适用于此网址?

为什么默认复制构造函数不适用于此类

了解为什么 dot 不适用于此特定示例