将每个点分成K+1(0<=i<=k)个点,代表该点之前有i条权值变为0的边
分层后找最短路
#include <bits/stdc++.h>
using namespace std;
const int maxn=100005;
const long long INF=1e18+5;
struct node{
int to,dis;
node (int a,int c):to(a),dis(c){};
};
struct nn{
int id;long long dis;
nn (long long a,int b):
dis(a),id(b){};
bool operator <(const nn &rhs)const
{
return dis > rhs.dis;
}
};
bool done[maxn*11];
int n,k;
long long d[maxn*11];
vector<node>G[maxn*11];
void dijkstra()
{
priority_queue<nn> Q;
for(int i=0; i<=(n-1)*(k+1)+k; i++) d[i]=INF;
d[0]=0;
memset(done,0,sizeof(done));
Q.push(nn(d[0],0));
while(!Q.empty())
{
nn x=Q.top();
Q.pop();
int u=x.id;
if(done[u]) continue;
done[u]=true;
for(int i=0;i<G[u].size();i++)
{
node e=G[u][i];
if(d[e.to]>d[u]+e.dis)
{
d[e.to]=d[u]+e.dis;
Q.push(nn(d[e.to],e.to));
}
}
}
}
int main()
{
int T,m,u,v,c;
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d",&n,&m,&k);
for (int i=0;i<=n*11;i++)
G[i].clear();
for (int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&c);
u--;v--;
//分层
for (int j=0;j<=k;j++)
{
G[u*(k+1)+j].push_back(node(v*(k+1)+j,c));
if (j<k)
G[u*(k+1)+j].push_back(node(v*(k+1)+j+1,0));
}
}
dijkstra();
long long ans=INF;
ans= d[(n-1)*(k+1)+k];
printf("%lld\n",ans);
}
}