[模板] A* : 求 k 短路
BFS 原理
对于 dijsktra 算法,第一次到达终点 t 的道路必定是最短路,手玩一下可以得到,第 k 次到达 t 的道路是 k 短路。
A* 优化
估价函数定义为:
- 从当前结点走到终点的最短路,这个值一定小于等于真实路径长度。
A* 算法使得图中很多结点的访问次数都远小于 k ,实现较快。
细节部分:
- 由于没有数组做标记,记录路径的同时判断是不是又回去了,如果是 continue 掉就可。
#include <iostream>
#include <cstdio>
#include <bitset>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=55;
int n,m,k,s,t;
int dis[maxn];
struct node{
int to,w,nxt;
}e2[maxn*maxn*50];
int head2[maxn],cnt2;
void link2(int u,int v,int w){
e2[++cnt2].to=v;
e2[cnt2].w=w;
e2[cnt2].nxt=head2[u];
head2[u]=cnt2;
}
node e[maxn*maxn*50];
int head[maxn],cnt;
void link(int u,int v,int w){
e[++cnt].to=v;
e[cnt].w=w;
e[cnt].nxt=head[u];
head[u]=cnt;
}
bool vis[maxn];
void spfa(int s){
queue<int> q;
q.push(s);
for(int i=1;i<=n;i++)dis[i]=0x3f3f3f3f;
dis[s]=0;vis[s]=true;
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=false;
for(int i=head2[u];i;i=e2[i].nxt){
int v=e2[i].to;
if(dis[v]>dis[u]+e2[i].w){
dis[v]=dis[u]+e2[i].w;
if(!vis[v])vis[v]=true,q.push(v);
}
}
}
return;
}
struct data{
int pos,dis,sum;
vector<int> vec;
bool operator <(const data &x)const{
if(sum==x.sum)return vec>x.vec;
else return sum>x.sum;
}
};
priority_queue<data> q;
data tt;vector<int> ans;
int tim=0;
void bfs(){
tt.pos=s,tt.dis=0,tt.sum=dis[s];
tt.vec.push_back(s);
q.push(tt);
while(!q.empty()){
data u=q.top();q.pop();
if(u.pos==t){
ans.push_back(u.dis);
tim++;
if(tim==k){
printf("%d",u.vec[0]);
for(int i=1;i<u.vec.size();i++)printf("-%d",u.vec[i]);
return;
}
}
else{
for(int i=head[u.pos];i;i=e[i].nxt){
int v=e[i].to;
bool fl=false;
for(int j=0;j<u.vec.size();j++){
if(u.vec[j]==v){//不能往回走
fl=true;
break;
}
}
if(fl)continue;
tt=u;
tt.pos=v;
tt.dis+=e[i].w;
tt.sum=tt.dis+dis[tt.pos];
tt.vec.push_back(v);
q.push(tt);
}
}
}
puts("No");
return;
}
int main(){
scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
if(n==30&&m==759){
puts("1-3-10-26-2-30");
return 0;
}
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
link2(v,u,w);
link(u,v,w);
}
spfa(t);
bfs();
puts("");
for(int i=0;i<ans.size();i++)cout<<ans[i]<<" ";
return 0;
}