下面的代码是错误的,测评记录:
dis[s] = 0;
que.push(make_pair(0, s));
while(que.size()){
if(mk[que.top().second]){
que.pop();
continue;
}
mk[que.top().second] = 1;
for(auto ptr = mp[que.top().second].begin(); ptr < mp[que.top().second].end(); ++ptr){
if(dis[que.top().second] + ptr->second < dis[ptr->first]){
dis[ptr->first] = dis[que.top().second] + ptr->second;
que.push(make_pair(-dis[ptr->first], ptr->first));
}
}
que.pop();
}
改为用 tmp 接住堆顶元素立刻弹出后,就过了:
dis[s] = 0;
que.push(make_pair(0, s));
while(que.size()){
tmp = que.top().second;
que.pop();
if(mk[tmp]) continue;
mk[tmp] = 1;
for(auto ptr = mp[tmp].begin(); ptr < mp[tmp].end(); ++ptr){
if(dis[tmp] + ptr->second < dis[ptr->first]){
dis[ptr->first] = dis[tmp] + ptr->second;
que.push(make_pair(-dis[ptr->first], ptr->first));
}
}
}
我猜可能是因为用堆顶元素进行松弛操作后,新入堆的元素会改变堆顶元素,但仔细想,新入堆的元素最短路是不可能比原来的堆顶元素小的啊,不会改变堆顶元素。
原本这是个求助帖,写到一半自己突然想明白了。考虑权值为 0 的边,松弛后新进堆的元素最短路跟堆顶元素相等,可能改变堆顶元素。可能有其他人会跟我犯同样的错误,所以还是把帖子发出来作为提醒吧。