最短路径
我们都知道了最短路径的求法,单源最短路中我们有dijkstra和spfa
我们也知道,堆优化的dijkstra是最快的,现在附上代码来回顾回顾!
struct dyh_node{
int num, the_dis;
bool operator < (const dyh_node &rhs) const {
return the_dis > rhs.the_dis;
}
}dyh_h;
priority_queue<dyh_node> first_q;
堆优化相比普通的dijkstra就快在解决了循环找dis最小的节点!
注意,我们用大跟堆时,写的排序比较的大小要反起来,也就是the_dis > rhs.the_dis 而不是小于
inline void dijkstra(int the_beg, int the_enl){
memset(vis, 0, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
dis[the_enl] = 0;
dyh_h.num = the_enl;
dyh_h.the_dis = 0;
first_q.push(dyh_h);
while(!first_q.empty()){
dyh_node t = first_q.top(), ne;
first_q.pop();
if(vis[t.num]){
continue;
}
vis[t.num] = 1;
for(reg int i = 0; i < _G[t.num].size(); i++){
if(dis[_G[t.num][i].v] > dis[t.num] + _G[t.num][i].w && !vis[_G[t.num][i].v]){
dis[_G[t.num][i].v] = dis[t.num] + _G[t.num][i].w;
ne.num = _G[t.num][i].v;
ne.the_dis = dis[_G[t.num][i].v];
first_q.push(ne);
}
}
}
}
这就是堆优化了!v表示下一个节点,w表示权值。
第k短路
我们现在给出一个结论,我们现在把dijkstra改一改,就可以成功做出第k短路了,现在我们不需要vis 也不需要松弛,一直进行下去,直到第i个节点第k次出队,那么我们就找到了起点到i节点的第k短路了。自然,这个队列是一个普通的队列,不需要有顺序。
然而,这却不是最快的,我们可以用A*来提高速度,我们设h()为当前花费,g()为估计花费!
什么意思,也就是说,我们假设要找s节点到t节点的第k短路,我们现在已经从s节点走到i节点了,然后我们要从i节点走到节点
现在我们从s节点到i节点已经花费了h(),我们估计从i节点到t节点要走g(),这样在众多的i节点中,我们选择h()+g()最少的先进行,这样更快的求出第k短路!如何求g(),我们只需要建立一个反图,从t节点到i节点的最短路,就知道了g()了!
struct _node{
int h, g, id;
_node(int H, int dg, int ID){
h = H;
g = dg;
id = ID;
}
bool operator < (const _node &rhs) const {
return h + g > rhs.h + rhs.g;
}
};
priority_queue<_node> q;
inline int A_star(){
while(!q.empty()){
q.pop();
}
q.push(_node(0, dis[beg], beg));
int tot = 0;
while(!q.empty()){
_node t = q.top();
q.pop();
if(t.id == enl)
tot ++;
if(tot >= k){
return t.h;
}
for(reg int i = 0; i < G[t.id].size(); i++){
q.push(_node(t.h + G[t.id][i].w, dis[G[t.id][i].v], G[t.id][i].v));
}
}
return -1;
}
如果找不到第k短路,我们就直接输出-1!