一道A*算法求第k短路的模板题,但是!我有话要说。
可能因为学校老师比较水,我们讲迪杰斯特拉算法的时候老师讲了个n^2算法实现的,教科书上也他妈n^2,我也没细想
后来比赛的时候我自己优化了,结果一百度发现直接优先级队列,elogn。。。。。伤心,错过一道水题。
自己做了个模板,以后直接用。对了,A*算法确实有复杂的用法,但是我们这里只要利用他求第k短就行了。
至于估值函数 F=G+H 这里求H用了迪杰斯特拉算法。
#include<iostream>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int T,n,m,a,b,w;
ll inf=1e18;
typedef struct node { //dij and mp
int at;
ll len;
bool operator < (const node &te) const {
return len>te.len;
}
}node;
typedef struct _node { //Astar
int at;
ll len;
ll tot;
bool operator < (const _node &te) const {
return tot>te.tot;
}
}_node;
vector<node> mp[100005];
ll dis[100005];
ll dij(int go) {
priority_queue<node> q;
for(int i=1;i<=n;i++) {
dis[i]=inf;
}
dis[go]=0;
q.push(node{go,0});
while(!q.empty()) {
node e=q.top(); q.pop();//这里加跳出判断可以求出最短路,也就是单纯的dij
for(int i=0;i<mp[e.at].size();i++) {
node xe=mp[e.at][i];
if(e.len+xe.len<dis[xe.at]) {
dis[xe.at]=e.len+xe.len;
q.push(node{xe.at,e.len+xe.len});
}
}
}
return 0;//返回最短路径,这个题目不需要
}
ll Astar(int Start,int End,int Knum) {
priority_queue<_node> q;
q.push(_node{Start,0,dis[Start]});
while(!q.empty()) {
_node e=q.top(); q.pop();
if(e.at==End) {
Knum--;
if(Knum==0)
return e.tot;
}
for(int i=0;i<mp[e.at].size();i++) {
node xe=mp[e.at][i];
q.push(_node{xe.at,e.len+xe.len,e.len+xe.len+dis[xe.at]});
}
}
}
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) {
mp[i].clear();
}
for(int i=1;i<=m;i++) {
scanf("%d%d%d",&a,&b,&w);
mp[a].push_back(node{b,w});
mp[b].push_back(node{a,w});
}
int Start=1,End=n,Knum=2;//A*求第Knum段路
ll ans1=dij(n);
ll ansKnum=Astar(Start,End,Knum);
printf("%lld\n",ansKnum);
}
return 0;
}