[英]Dijkstra's algorithm question
在下面的代码中:
#define MAX_VERTICES 260000
#include <fstream>
#include <vector>
#include <queue>
#define endl '\n'
using namespace std;
struct edge {
int dest;
int length;
};
bool operator< (edge e1, edge e2) {
return e1.length > e2.length;
}
int C, P, P0, P1, P2;
vector<edge> edges[MAX_VERTICES];
int best1[MAX_VERTICES];
int best2[MAX_VERTICES];
void dijkstra (int start, int* best) {
for (int i = 0; i < P; i++) best[i] = -1;
best[start] = 0;
priority_queue<edge> pq;
edge first = { start, 0 };
pq.push(first);
while (!pq.empty()) {
edge next = pq.top();
pq.pop();
if (next.length != best[next.dest]) continue;
for (vector<edge>::iterator i = edges[next.dest].begin(); i != edges[next.dest].end(); i++) {
if (best[i->dest] == -1 || next.length + i->length < best[i->dest]) {
best[i->dest] = next.length + i->length;
edge e = { i->dest, next.length+i->length };
pq.push(e);
}
}
}
}
int main () {
ifstream inp("apple.in");
ofstream outp("apple.out");
inp >> C >> P >> P0 >> P1 >> P2;
P0--, P1--, P2--;
for (int i = 0; i < C; i++) {
int a, b;
int l;
inp >> a >> b >> l;
a--, b--;
edge e = { b, l };
edges[a].push_back(e);
e.dest = a;
edges[b].push_back(e);
}
dijkstra (P1, best1); // find shortest distances from P1 to other nodes
dijkstra (P2, best2); // find shortest distances from P2 to other nodes
int ans = best1[P0]+best1[P2]; // path: PB->...->PA1->...->PA2
if (best2[P0]+best2[P1] < ans)
ans = best2[P0]+best2[P1]; // path: PB->...->PA2->...->PA1
outp << ans << endl;
return 0;
}
这是什么: if (next.length != best[next.dest]) continue;
用于? 这是为了避免我们遇到循环的情况会给我们相同的答案吗?
谢谢!
我想你正在考虑你的priority_queue包含2倍相同边缘的情况,但每个都有不同的“长度”。
如果你推动长度为Y的边缘X,然后再次推动边缘X,这可能会发生,但这次它的长度<Y.这就是为什么,如果边缘的长度不是最低的那么你呢?到目前为止已找到该边缘,你在该循环的迭代中省略它。
该行是一种处理c ++的priority_queue没有reduce_key函数这一事实的方法。
也就是说,当你执行pq.push(e)
并且堆中已存在具有相同目标的边时,您希望减少堆中已存在的边的键。 使用c ++的priority_queue并不容易做到这一点,因此处理它的一种简单方法是允许堆中的多个边对应于同一目标,并忽略从堆中弹出的第一个(对于每个dest)。
请注意,这会将复杂性从O(ElogV)
更改为O(ElogE)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.