【问题标题】:Dijsktra's Algorithm Implmentation : Mice and MazeDijkstra 的算法实现:老鼠和迷宫
【发布时间】:2014-08-02 04:50:38
【问题描述】:

This 是一个简单的问题,涉及 Dijkstra 算法,用于查找以给定顶点为根的最短距离树。以下是被接受的代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<deque>
#include<queue>
#include<utility>
#include<vector>
#include<climits>
#include<algorithm>
#include<stack>
using namespace std;
bool debug=false;
typedef long long int lld;
typedef unsigned long long int llu;
struct compare_vertex{
    bool operator()(const pair<int,lld> &p1 , const pair<int,lld> p2){
        return p1.second<p2.second;
    }
};
typedef priority_queue<pair<int,lld> , vector<pair<int,lld> > , compare_vertex> node_pq;
class Solver{
    int n , e , t , m;
    vector<deque<pair<int,lld> > > adjList;
    vector<lld> min_dist;
    node_pq pq;
    void push_node(int index , lld dist){
        if(min_dist[index] < dist){
            return;
        }
        pq.push(make_pair(index , dist));
        min_dist[index] = dist;
    }
public:
    Solver(){
        scanf("%d",&n);
        adjList = vector<deque<pair<int,lld> > >(n);
        min_dist= vector<lld>(n , INT_MAX);

        scanf("%d",&e);
        --e;
        scanf("%d",&t);
        scanf("%d",&m);

        int x , y ;
        lld z;
        for(int i=0;i<m;++i){
            scanf("%d %d %lld",&x , &y , &z);
            --x;--y;
            adjList[y].push_back(make_pair(x , z));
        }
    }
    int solve(){
        push_node(e , 0);

        int size;
        pair<int,lld> vertex;
        while(!pq.empty()){
            vertex = pq.top();
            pq.pop();

            size = adjList[vertex.first].size();
            for(int i=0;i<size;++i){
                push_node(adjList[vertex.first][i].first , vertex.second +   adjList[vertex.first][i].second);
            }
        }

        int count = 0;
        for(int i=0;i<n;++i){
            count += min_dist[i]<=t ? 1 : 0;
        }

        return count;
    }
};
int main(int argc , char **argv)
{
    if(argc>1 && strcmp(argv[1],"DEBUG")==0) debug=true;
    Solver s;
    printf("%d\n",s.solve());
    return 0;
}

算法是贪心的,所以我们逐渐选择离树最近的顶点。这意味着,一旦选择了一个顶点,就不会有任何从根开始的更短路径。因此,重新访问一个顶点以查看当前距离是否比之前的距离短是徒劳的(这是我们在 Bellman-Ford 算法中所做的事情)。所以,push_node 函数的返回条件应该是:

if(min_dist[index] != INT_MAX){
    return; 
}

但这给出了错误的答案。最初我认为 int 数据类型可能存在溢出,所以我将所有距离变量更改为 long long int(这让我又经历了 2 个测试用例)。但上面仍然给出了错误的答案。我哪里错了?

【问题讨论】:

  • @user21311678 你还应该包括测试用例,你现在得到什么,你期望得到什么,以便人们更容易帮助你。帮助我们帮助您。
  • Spoj 不显示代码失败的测试用例。所以我不知道为什么这给出了错误的答案。
  • 更改返回条件使代码通过所有测试用例。但这不应该发生。从逻辑上讲,以 WA 结尾的返回条件应该有效。这就是我能得出的结论。

标签: c++ algorithm dijkstra


【解决方案1】:

一旦从priority_queue中弹出,您就可以保证它是最短路径,但当节点只是计算节点的邻居时则不能。

目前,您将min_dist 设置为push_node(对于邻居也是如此)。

以3个节点A、B、E(exit)为例:

E <- A 4
E <- B 1
B <- A 1

你从 E 开始,然后是 push_node(A, 4) 和 push_node(B, 1) 所以你已经设置了所有min_dist

当您弹出B 时,您将纠正min_dist(A) 的值较低。

作为当前解决方案的替代方案,您可以在弹出时检查 min_dist 是否未设置,然后设置 min_dist 并从该节点传播。

【讨论】:

    【解决方案2】:

    只要顶点没有从优先级队列中弹出,即只要它不是离根最近的未完成顶点,您仍然可以找到较短的路径。如果你这样做了

    if(min_dist[index] != INT_MAX){
        return; 
    }
    

    您只能找到一条路径,并且您会忽略稍后找到的较短路径,从而为您提供错误的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-22
      • 1970-01-01
      • 2021-06-25
      • 2015-06-02
      相关资源
      最近更新 更多