先求每个点到目地T的最短距离。
这一步可以将图的每条边反向,做单源最短路求得。
然后就是在图上搜索。
可以用优先队列来实现搜索状态的筛选。
f=g+h
g为搜索到此点已经走过的距离,h为此点到T的最短距离。
当第K次搜到T,此时的g+h就是第K短路。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
int N,M;
int S,T,K;
struct edge
{
int to,cost,next;
}E1[100005],E2[100005];
int esize1,esize2;
int head1[1005],head2[1005];
int d[1005];
void init()
{
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
esize1=esize2=0;
}
void addedge(int from,int to,int cost)
{
E1[esize1].to=to;
E1[esize1].cost=cost;
E1[esize1].next=head1[from];
head1[from]=esize1++;
E2[esize2].to=from;
E2[esize2].cost=cost;
E2[esize2].next=head2[to];
head2[to]=esize2++;
}
void dij()
{
typedef pair<int,int> P;
memset(d,0x3f,sizeof(d));
priority_queue<P,vector<P>,greater<P> > que;
d[T]=0;
que.push(P(0,T));
while(!que.empty())
{
P tmp=que.top(); que.pop();
if(d[tmp.second]<tmp.first) continue;
for(int i=head2[tmp.second];i!=-1;i=E2[i].next)
{
if(d[E2[i].to]>tmp.first+E2[i].cost)
{
d[E2[i].to]=tmp.first+E2[i].cost;
que.push(P(d[E2[i].to],E2[i].to));
}
}
}
}
struct step
{
int v;
int f,h;
step (int a=0,int b=0,int c=0):v(a),f(b),h(c){}
bool operator>(const step &tmp)const
{
return f+h>tmp.f+tmp.h;
}
};
int astar()
{
priority_queue<step,vector<step>,greater<step> > que;
que.push(step(S,0,d[S]));
int cnt=0;
while(!que.empty())
{
step now=que.top(); que.pop();
//printf("v=%d f=%d h=%d\n",now.v,now.f,now.h);
//system("pause");
if(now.v==T)
{
cnt++;
if(cnt==K) return now.f+now.h;
}
for(int i=head1[now.v];i!=-1;i=E1[i].next)
{
que.push(step(E1[i].to, now.f+E1[i].cost ,d[E1[i].to]));
}
}
return -1;
}
int main()
{
while(~scanf("%d%d",&N,&M))
{
init();
int a,b,c;
for(int i=0;i<M;i++)
{
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
}
scanf("%d%d%d",&S,&T,&K);
if(S==T) K++;
dij();
printf("%d\n",astar());
}
}