#题解
题目大意 给你n个点m条边k次将边代价改为0的机会 问你从1到n最短路
分层最短路 类似dp进行状态转移 据说是卡SPFA
#AC代码
#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int MAXN = 1e5 + 10;
struct edge
{
int v, c;
};
struct qnode
{
int u, cnt;
ll c;
bool operator < (const qnode &oth) const
{
return this->c > oth.c;
}
};
ll cot[MAXN][20];
int vis[MAXN][20];
vector<edge> adl[MAXN];
int main()
{
#ifdef LOCAL
freopen("C:/input.txt", "r", stdin);
#endif
int T;
cin >> T;
while (T--)
{
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i <= n; i++)
adl[i].clear();
memset(cot, 0x3f, sizeof(cot));
memset(vis, 0, sizeof(vis));
for (int i = 0; i < m; i++)
{
int u, v, c;
scanf("%d%d%d", &u, &v, &c);
adl[u].push_back({ v, c });
}
for (int i = 0; i <= k; i++)
cot[1][i] = 0;
priority_queue<qnode> pq;
pq.push(qnode{ 1, k, 0 });
while (!pq.empty())
{
int u = pq.top().u, cnt = pq.top().cnt;
ll c = pq.top().c;
pq.pop();
if (vis[u][cnt])
continue;
vis[u][cnt] = 1;
for (int i = 0; i < adl[u].size(); i++)
{
int v = adl[u][i].v, d = adl[u][i].c;
if (cot[v][cnt] > cot[u][cnt] + d)
{
cot[v][cnt] = cot[u][cnt] + d;
pq.push(qnode{ v, cnt, cot[v][cnt] });
}
if (cnt && cot[v][cnt - 1] > cot[u][cnt])
{
cot[v][cnt - 1] = cot[u][cnt];
pq.push(qnode{ v, cnt - 1, cot[v][cnt - 1] });
}
}
}
ll ans = LINF;
for (int i = 0; i <= k; i++)
ans = min(ans, cot[n][i]);
if (ans == LINF)
cout << -1 << endl;
else
cout << ans << endl;
}
return 0;
}