我们设置dis[i][k]表示走到第i号点,免费经过了k条边的最短路。
对于我们当前找到的终点,尝试起点的状态去更新,不选择此条边免费的状态和选择此条边免费的状态,再将这两个状态压入队列去更新可以到达的其他状态。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<map>
#include<stack>
#include<queue>
#include<set>
#define maxn 200005
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define LL long long
#define ev 2.71828182
using namespace std;
const double PI=acos(-1.0);
int t,n,m,k;
struct node
{
int from,cs;
LL w;
friend bool operator <(node a,node b)
{
return a.w>b.w;
}
};
struct knode
{
int to,w;
};
vector<knode>v[maxn];
int dis[maxn][20];//dis[i][k]表示走到i点,k条边置0时的最短距离
bool book[maxn][20];
void dijkstra()
{
memset(dis,0x3f,sizeof(dis));
memset(book,false,sizeof(book));
priority_queue<node>q;
node h={1,0,0};
q.push(h);
while(!q.empty())
{
node t=q.top();
q.pop();
if(book[t.from][t.cs])
continue;
book[t.from][t.cs]=true;
for(int i=0;i<v[t.from].size();i++)
{
int mb=v[t.from][i].to;
int bw=v[t.from][i].w;
if(dis[mb][t.cs]>t.w+bw)
{
dis[mb][t.cs]=t.w+bw;
q.push(node{mb,t.cs,dis[mb][t.cs]});
}
if(t.cs+1<=k)
{
if(dis[mb][t.cs+1]>t.w+0)
{
dis[mb][t.cs+1]=t.w;
q.push(node{mb,t.cs+1,dis[mb][t.cs+1]});
}
}
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>m>>k;
for(int i=0;i<maxn;i++)
v[i].clear();
for(int i=0;i<m;i++)
{
int a,b,c;
cin>>a>>b>>c;
knode z;
z.to=b;z.w=c;
v[a].push_back(z);
}
dijkstra();
cout << dis[n][k] << endl;
}
return 0;
}