题目链接
学习博客:https://blog.csdn.net/Z_Mendez/article/details/47057461
k短路没有我想象的那么难,还是很容易理解的
求s点到t点的第k短路径
先求出t到所有点的最短路径,用g[i]表示t到i的距离
从s开始”bfs“,按照(g[i]+bfs路过的长度)构造优先队列,比如刚开始bfs路过长度为0,所在点为s
一直选择最小的(g[i]+bfs路过的长度),第一次到达t一定是从s沿着最短路径到达。
直到第k次到达t
理解代码可能更容易些
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<set>
#include<vector>
using namespace std;
#define ll long long
const int maxn=1e3+5;
const int INF=1e9;
struct line
{
int to,w;
line(int _to,int _w)
{
to=_to,w=_w;
}
};
vector<line>ma1[maxn],ma2[maxn];//ma1为真实的路线,ma2为逆的,为了计算终点到各个点的最短距离
int g[maxn],vis[maxn];//g数组为终点到各个点的最短距离
int n,m,s,t,k,time;
struct node
{
int x,time;//当前节点走过的距离time + x到终点的距离就是这条路线的距离
node(int _x,int _time)
{
x=_x,time=_time;
}
bool operator<(const node &a)const
{
return g[x]+time>g[a.x]+a.time;
}
};
void dij()//为了构造g数组
{
for(int i=1;i<=n;i++)vis[i]=0,g[i]=1e9;
g[t]=0;
for(int i=1;i<=n;i++)
{
int inde,mi=1e9+10;
for(int j=1;j<=n;j++)
{
if(vis[j]==0&&mi>g[j])
{
mi=g[j];
inde=j;
}
}
vis[inde]=1;
for(int j=0;j<ma2[inde].size();j++)
g[ma2[inde][j].to]=min(g[ma2[inde][j].to],g[inde]+ma2[inde][j].w);
}
}
int astar()//根据g数组指引“bfs”运动
{
priority_queue<node>que;
que.push(node(s,0));
if(s==t)
k++;
while(que.size())
{
node now=que.top();
que.pop();
if(now.x==t)time++; //到达终点
if(time==k)return now.time;
for(int i=0;i<ma1[now.x].size();i++)
{
que.push(node(ma1[now.x][i].to,now.time+ma1[now.x][i].w));
}
}
return -1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int a,b,c;
scanf("%d %d %d",&a,&b,&c);
ma1[a].push_back(line(b,c));
ma2[b].push_back(line(a,c));
}
cin>>s>>t>>k;
dij();
cout<<astar()<<endl;;
return 0;
}