用得不多,就不讲那么详细了
功能实现
A*算法最主要的部分就是它的估价函数(f(i)=g(i)+h(i))
设(g(i))为到达某点已经付出的代价,(h(i))为该点到终点的估计代价
则估价函数则为两者之和
放入优先队列中,将会先处理估计总代价最小的状态,以取得(k)短路
求从点(st)到点(ed)的第(k)短路的长度
如上面估价函数所需要的,我们需要先求出(h(i)),即预处理出图中每个点到终点(ed)的估计代价(最短路径)
对于多起点同终点类型问题,可以将有向图中所有边全部取反,获得一张反向图,然后以(ed)为起点跑遍整张反向图求出最短路即可
所以此时只需要跑一边SPFA求出(ed)到任意点的最短距离(dis[i]),即可当作正向图中的(h(i))
然后便是Astar的主要部分
建立一个新结构体(node)保存搜索过程中每一种状态({to,g(i),f(i)}),根据上述估价函数,重载运算符时将(f(i))作为主关键词,将(g(i))作为次关键词
从小到大排序(放入小顶堆优先队列中),或从大到小排序(放入大顶堆优先队列中)
以类似bfs的方法,从起点(st)开始搜索,以优先队列作为搜索队列
每当搜索到一次(ed)点,就表明找到了一条最短路,直到第(k)次搜索到(ed)点时,便可以直接返回当前状态的(g(i))作为第(k)短路的代价
若在队列为空前均没有返回,说明不存在第(k)短路
代码
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const int maxn=100050;
struct node
{
int to,g,f;
bool operator < (const node &r) const
{
if(r.f==f)
return r.g<g;
return r.f<f;
} //从大到小排序,放入大顶堆内(使用时就会变成从小到大)
};
vector<P> G[maxn]; //正向图,{first,second}={to,cost}
vector<P> IG[maxn]; //反向图
bool inq[maxn];
int dis[maxn]; //dis[i]为i到ed的最短路径
void init(int n)
{
for(int i=1;i<=n;i++)
{
G[i].clear();
IG[i].clear();
}
}
void SPFA(int n,int st)
{
queue<int> que;
for(int i=1;i<=n;i++)
{
dis[i]=INF;
inq[i]=false;
}
dis[st]=0;
inq[st]=true;
que.push(st);
while(!que.empty())
{
int cur=que.front();
que.pop();
inq[cur]=false;
for(P &pd:IG[cur])
{
if(dis[pd.first]>dis[cur]+pd.second)
{
dis[pd.first]=dis[cur]+pd.second;
if(!inq[pd.first])
{
inq[pd.first]=true;
que.push(pd.first);
}
}
}
}
}
int AStar(int n,int st,int ed,int k)
{
priority_queue<node> pq;
if(st==ed)
k++;
node tmp=node{st,0,dis[st]};
int cnt=0;
pq.push(tmp);
while(!pq.empty())
{
node nd=pq.top();
pq.pop();
if(nd.to==ed)
cnt++; //找到一条最短路
if(cnt==k)
return nd.g; //当前找到的是k短路
for(P &pd:G[nd.to])
{
tmp.to=pd.first; //去往的节点
tmp.g=nd.g+pd.second; //当前代价g
tmp.f=tmp.g+dis[pd.first]; //估计代价f=g+h
pq.push(tmp);
}
}
return -1;
}
int main()
{
int n,m,u,v,c,st,ed,k;
scanf("%d%d",&n,&m);
init(n);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&c);
G[u].push_back(P(v,c));
IG[v].push_back(P(u,c));
}
scanf("%d%d%d",&st,&ed,&k);
SPFA(n,ed);
printf("%d
",AStar(n,st,ed,k));
return 0;
}
实在没找到啥非常模板的模板题,略过——