CCCPaste
#include <bits/stdc++.h>

using namespace std;

// 定义无穷大常量,用于初始化距离数组
constexpr int inf = 0x3f3f3f3f;

// 定义边的结构体,用于邻接表和优先队列
struct Edge {
int u, w; // u: 边的目标节点 (target node), w: 边的权值 (cost)

// 重载小于号运算符 <
// std::priority_queue 默认是大根堆(最大的元素在堆顶)
// 为了让它变成小根堆(最小权值的边在堆顶),我们需要反转比较逻辑
// 当当前边的权值 w 大于对方的权值 o.w 时,判定为“真”,使其沉底
bool operator< (const Edge& o) const {
return w > o.w;
}
};

int main() {
// 关闭输入输出同步,加速 I/O 操作
ios::sync_with_stdio(false);
cin.tie(nullptr);

int n, m, k, s, t;
// 输入:城市数 n,航线数 m,免费次数 k,起点 s,终点 t
cin >> n >> m >> k >> s >> t;

// 坐标偏移处理:题目给出的城市编号是 0 ~ n-1
// 这里将其统一加 1,变为 1 ~ n,符合部分人的编程习惯(不加也可以,只要统一就行)
s++; t++;

// 初始化邻接表
// 分层图共有 k+1 层(第0层到第k层)
// 总节点数约为 n * (k + 1),为了防止越界,开大一点点
vector<vector<Edge> > adj((k + 1) * n + 1);

// 读取 m 条航线信息
for (int i = 1; i <= m; ++i) {
int u, v, w;
cin >> u >> v >> w;
u++; v++; // 同样将输入的节点编号加 1

// 1. 建立第 0 层的原始边(完全不使用免费票的情况)
// 连接 u 和 v,权值为 w
adj[u].push_back({v, w});
adj[v].push_back({u, w});

// 2. 遍历第 1 层到第 k 层,构建分层图的其余部分
for (int j = 1; j <= k; ++j) {
// --- 策略 A:同层移动(不使用免费票) ---
// 在第 j 层,连接 u 和 v,花费仍然是 w
// 节点编号映射规则:第 j 层的节点 u 编号为 j * n + u
adj[j * n + u].push_back({j * n + v, w});
adj[j * n + v].push_back({j * n + u, w});

// --- 策略 B:跨层移动(使用免费票) ---
// 从第 j-1 层跨越到第 j 层,花费为 0
// 这代表:在当前这条航线上使用了 1 次免费机会

// 从 u (第 j-1 层) -> v (第 j 层),权值 0
adj[(j - 1) * n + u].push_back({j * n + v, 0});

// 从 v (第 j-1 层) -> u (第 j 层),权值 0
adj[(j - 1) * n + v].push_back({j * n + u, 0});
}
}

// Dijkstra 算法标准模板
priority_queue<Edge> q;
// dist 数组初始化为无穷大
vector<int> dist((k + 1) * n + 1, inf);
// vis 数组标记节点是否已确定最短路
vector<bool> vis((k + 1) * n + 1);

// 起点入队:起点 s 位于第 0 层,距离为 0
q.push({s, 0});
dist[s] = 0;

while (!q.empty()) {
Edge now = q.top();
q.pop();
int u = now.u; // 当前节点编号(包含了层级信息)

// 如果该节点已经处理过最优解,跳过
if (vis[u])
continue;
vis[u] = true;

// 遍历所有邻接边
for (int i = 0; i < adj[u].size(); ++i) {
int v = adj[u][i].u; // 目标节点
int w = adj[u][i].w; // 边权

// 松弛操作:如果通过 u 到达 v 的距离更短,则更新
if (dist[v] > dist[u] + w) {
dist[v] = dist[u] + w;
q.push({v, dist[v]});
}
}
}

// 统计答案
// 最终到达终点 t 时,可能使用了 0 次、1 次 ... 或 k 次免费票
// 这些状态分别对应分层图中的 t, n+t, 2n+t ... k*n+t
// 取所有可能层级中终点距离的最小值
int ans = inf;
for (int i = 0; i <= k; ++i) {
ans = min(ans, dist[i * n + t]);
}

cout << ans << "\n";

return 0;
}