题面
给定一张N个点(编号1,2…N),M条边的有向图,求从起点S到终点T的第K短路的长度,路径允许重复经过点或边。
注意: 每条最短路中至少要包含一条边。
输入格式
第一行包含两个整数N和M。
接下来M行,每行包含三个整数A,B和L,表示点A与点B之间存在有向边,且边长为L。
最后一行包含三个整数S,T和K,分别表示起点S,终点T和第K短路。
输出格式
输出占一行,包含一个整数,表示第K短路的长度,如果第K短路不存在,则输出“-1”。
数据范围
1≤S,T≤N≤1000,
0≤M≤105,
1≤K≤1000,
1≤L≤100
输入样例:
2 2
1 2 5
2 1 4
1 2 2
输出样例:
14
思路
k短路的板子题,我们先从终点开始跑一边最短路作为我们a里面要用的估价函数。然后去跑A,当我们第k次到达终点,那么这个距离就是我们要求的第k短路。
代码实现
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const int maxn=200010;
const int N=1010;
typedef pair<int,int > PII;
typedef pair<int,PII> PIII;
int m,n,s,t,k;
int cnt,tot,head1[maxn],head2[maxn];
int f[N],dis[N],vis[N];
struct edge {
int w,v,nex;
edge (int w=0,int v=0,int nex=0) :w(w), v(v), nex(nex) {}
}e1[maxn],e2[maxn];
inline void add1 (int u,int v,int w) {
e1[++cnt]=edge (w,v,head1[u]);
head1[u]=cnt;
}
inline void add2 (int u,int v,int w) {
e2[++tot]=edge (w,v,head2[u]);
head2[u]=tot;
}
inline void init () {
memset (vis,0,sizeof (vis));
memset (dis,0x3f3f3f3f,sizeof (dis));
memset (head1,-1,sizeof (head1));
memset (head2,-1,sizeof (head2));
}
inline void dijkstra () {
priority_queue <PII,vector<PII>,greater <PII> > q;
dis[t]=0;
q.push (PII{0,t});
while (q.size ()) {
PII u=q.top ();
q.pop ();
if (vis[u.second]) continue;
vis[u.second]=1;
for (int i=head1[u.second];i!=-1;i=e1[i].nex) {
int v=e1[i].v;
if (dis[v]>dis[u.second]+e1[i].w) {
dis[v]=dis[u.second]+e1[i].w;
q.push (PII{dis[v],v});
}
}
}
memcpy (f,dis,sizeof (dis));
}
inline int a_star () {
priority_queue<PIII,vector<PIII>,greater <PIII> > q;
q.push (PIII{f[s],{0,s}});
memset (vis,0,sizeof (vis));
while (q.size ()) {
PIII u=q.top ();
q.pop ();
int ver=u.second.second,distance=u.second.first;
if (vis[ver]>=k) continue;
vis[ver]++;
if (ver==t&&vis[ver]==k) return distance;
for (int i=head2[ver];i!=-1;i=e2[i].nex) {
int v=e2[i].v;
if (vis[v]<k) {
q.push ({distance+e2[i].w+f[v],{distance+e2[i].w,v}});
}
}
}
return -1;
}
int main () {
cin>>n>>m;
init ();
for (int i=1;i<=m;i++) {
int x,y,z;
cin>>x>>y>>z;
add2 (x,y,z);
add1 (y,x,z);
}
cin>>s>>t>>k;
if (t==s) k++;
dijkstra ();
cout<<a_star()<<endl;
return 0;
}