/* POJ 2449 Remmarguts' Date -- 有向图第k短路(有重边) 反向求单元点最短路(Dijkstra) 然后正向搜一遍 (用优先队列搞/A*) */ #include <cmath> #include <queue> #include <vector> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <assert.h> //#include <ctime> using namespace std; #define CLR(c,v) memset(c,v,sizeof(c)) typedef pair<int,int> pii; typedef long long ll; const double eps = 1e-6; const int N = 1e3 + 10; const int INF = (0x03ffffff); const int inf = -(0x03ffffff); // m1[id][i].first表示 (id点)的第i条边连到(first点) 其长度为.second // m1为原始图,m2为反向图 vector<pii> m1[N],m2[N]; int G[N]; // 估计函数 int e,s,k; // e起点 s终点 第k短 struct P{ int p,g,h; P(){} P(const P& Val){p=Val.p;g=Val.g;h=Val.h;} P(int p,int g,int h):p(p),g(g),h(h){} bool operator < (const P& Val) const{ //优先g+h小的出来 return Val.g+Val.h < g+h; } }; void pre(int n){ //Dijkstra 求各点到终点的最短路 bool vis[N]; CLR(vis,0); for(int i = 1 ; i < N ; i++)G[i] = INF; G[e] = 0; for(int i = 1 ; i <= n ; i++){ int minid = 0; for(int j = 1 ; j <= n ; j++){ if(vis[j] || (minid && G[minid]<=G[j]) )continue; minid = j; } vis[minid] = 1; int size = m2[minid].size(); for(int j = 0 ; j < size ; j++){ if( G[ m2[minid][j].first ] > G[minid]+m2[minid][j].second) G[ m2[minid][j].first ] = G[minid]+m2[minid][j].second; } } } int solve(int n){ // 从原点出发,把相邻的点全部push进队列,H()为当前走过的路程,G()为估计以后的路程 // 每次出队G()+H()最小的点 // 直到第k次找到终点,此时的G()+H()为结果 priority_queue <P> q; int ts[N];CLR(ts,0); // ts[i] 记录i元素出队过几次,出队一次表示找到一条'最'短路 P now , b(s,G[s],0); q.push( b ); while( !q.empty()){ now = q.top();q.pop(); if(++ts[now.p] > k)continue; // 这个点出队次数大于了k则不满足要求 if(now.p == e && ts[now.p] == k )return now.h+now.g; int size = m1[now.p].size(); for(int i = 0 ; i < size ; i++){ // (now.p),(next.first) 两点之间的距离为 next.second pii next = m1[now.p][i]; b = P(next.first , G[next.first], now.h+next.second); q.push( b ); } } return -1; } int main(){ //freopen("in.txt","r",stdin); int n,m; while(cin >> n >> m){ for(int i = 0 ; i < m ; i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); m1[a].push_back(make_pair(b,c)); m2[b].push_back(make_pair(a,c)); } cin >> s >> e >> k; if(s==e)k++; // 这种情况最短路肯定是不用走就能到达,但是题目要求必须走 pre(n); cout << solve(n) << endl; for(int i = 0; i < N ; i++) m1[i].clear(),m2[i].clear(); } return 0; }