/*
*算法引入:
*在單源點最短路徑問題中,實際運用時還需知道最短路徑外,次短路或者第三短路;
*即要知道多條最短路,并排出其長度增加的順序,即為K最短路問題;
*
*算法思想:
*單源點最短路徑+進階搜尋A*;
*A*算法結合了啟發式方法和形式化方法;
*啟發式方法通過充分利用圖給出的資訊來動态地做出決定而使搜尋次數大大降低;
*形式化方法不利用圖給出的資訊,而僅通過數學的形式分析;
*
*算法通過一個估價函數f(h)來估計圖中的目前點p到終點的距離,并由此決定它的搜尋方向;
*當這條路徑失敗時,它會嘗試其他路徑;
*對于A*,估價函數=目前值+目前位置到終點的距離,即f(p)=g(p)+h(p),每次擴充估價函數值最小的一個;
*
*對于K短路算法來說,g(p)為目前從s到p所走的路徑的長度;h(p)為點p到t的最短路的長度;
*f(p)的意義為從s按照目前路徑走到p後再走到終點t一共至少要走多遠;
*
*為了加速計算,h(p)需要在A*搜尋之前進行預處理,隻要将原圖的所有邊反向,再從終點t做一次單源點最短路徑就能得到每個點的h(p)了;
*
*算法步驟:
*(1),将有向圖的所有邊反向,以原終點t為源點,求解t到所有點的最短距離;
*(2),建立一個優先隊列,将源點s加入到隊列中;
*(3),從優先級隊列中彈出f(p)最小的點p,如果點p就是t,則計算t出隊的次數;
*如果目前為t的第k次出隊,則目前路徑的長度就是s到t的第k短路的長度,算法結束;
*否則周遊與p相連的所有的邊,将擴充出的到p的鄰接點資訊加入到優先級隊列;
*
*算法測試:
*PKU2449(Remmarguts' Date)
*
*題目大意:
*求從s到t的第k短路的長度;
*/
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<cstdio>
#include<climits>
#include<algorithm>
using namespace std;
const int INF=0xffffff;
const int N=1010;
const int M=100010;
struct node1
{
int to;
int w;
int next;
};
node1 edge1[M],edge2[M];
int head1[M],head2[M];
int idx1,idx2;
int dist[N];
struct node2
{
int to;
//g(p)為目前從s到p所走的路徑的長度;h(p)為點p到t的最短路的長度;
int g,f;//f=g+h,f(p)的意義為從s按照目前路徑走到p後再走到終點t一共至少要走多遠;
bool operator<(const node2 &r ) const
{
if(r.f==f)
return r.g<g;
return r.f<f;
}
};
void Addedge1(int u,int v,int w)
{
edge1[idx1].w=w;
edge1[idx1].to=v;
edge1[idx1].next=head1[u];
head1[u]=idx1++;
}
void Addedge2(int u,int v,int w)
{
edge2[idx2].w=w;
edge2[idx2].to=v;
edge2[idx2].next=head2[u];
head2[u]=idx2++;
}
bool SPFA(int s,int n,int head[],node1 edge[],int dist[])
{
queue<int>Q1;
int inq[N];
for(int i=0; i<=n; i++)
{
dist[i]=INF;
inq[i]=0;
}
dist[s]=0;
Q1.push(s);
inq[s]++;
while(!Q1.empty())
{
int q=Q1.front();
Q1.pop();
inq[q]--;
if(inq[q]>n)//負權環
return false;
int k=head[q];
while(k>=0)
{
if(dist[edge[k].to]>dist[q]+edge[k].w)
{
dist[edge[k].to]=edge[k].w+dist[q];
if(!inq[edge[k].to])
{
inq[edge[k].to]++;
Q1.push(edge[k].to);
}
}
k=edge[k].next;
}
}
return true;
}
int A_star(int s,int t,int n,int k,int head[],node1 edge[],int dist[])
{
node2 e,ne;
int cnt=0;
priority_queue<node2>Q;
if(s==t)//當s==t時,距離為0的路不能算在這k短路中,是以需要求k+1短路;
k++;
if(dist[s]==INF)
return -1;
e.to=s;
e.g=0;
e.f=e.g+dist[e.to];
Q.push(e);
while(!Q.empty())
{
e=Q.top();
Q.pop();
if(e.to==t)//找到一條最短路徑
{
cnt++;
}
if(cnt==k)//找到k短路
{
return e.g;
}
for(int i=head[e.to]; i!=-1; i=edge[i].next)
{
ne.to=edge[i].to;
ne.g=e.g+edge[i].w;
ne.f=ne.g+dist[ne.to];
Q.push(ne);
}
}
return -1;
}
int main()
{
int n,m;
//freopen("C:\\Users\\Administrator\\Desktop\\kd.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
memset(head1, -1, sizeof(head1));
memset(head2, -1, sizeof(head2));
idx1=idx2=0;
int u,v,w;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&u,&v,&w);
Addedge1(u,v,w);
Addedge2(v,u,w);
}
int s,t,k;
scanf("%d%d%d",&s,&t,&k);
SPFA(t,n,head2,edge2,dist);//以原終點t為源點,求反向圖中t到所有點的最短距離;
int res=A_star(s,t,n,k,head1,edge1,dist);
printf("%d\n",res);
}
return 0;
}