拆点,每个点拆成用了ki次免费航线,然后跑一遍Spfa就好了。
不过裸Spfa可能会超时(反正我的跑了6000多MS),还是用Dijkstra的好。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int inf=1e9;
struct Edge{int to,next,v;}e[100005];
int head[10005],d[10005][15],cnt,n,m,k;
bool inq[10005][15];
void ins(int u,int v,int w){
cnt++;e[cnt].to=v;
e[cnt].next=head[u];head[u]=cnt;
e[cnt].v=w;
}
void spfa(int s){
memset(d,0x3f,sizeof(d));
d[s][0]=0;queue<int>q,t;q.push(s);t.push(0);
while(!q.empty()){
int u=q.front(),ti=t.front();q.pop();t.pop();
inq[u][ti]=false;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(d[v][ti]>d[u][ti]+e[i].v){
d[v][ti]=d[u][ti]+e[i].v;
if(!inq[v][ti]){inq[v][ti]=true;q.push(v);t.push(ti);}
}
if(ti<k&&d[v][ti+1]>d[u][ti]){
d[v][ti+1]=d[u][ti];
if(!inq[v][ti+1]){inq[v][ti+1]=true;q.push(v);t.push(ti+1);}
}
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
int s,t;scanf("%d%d",&s,&t);
int a,b,c;
while(m--){
scanf("%d%d%d",&a,&b,&c);
ins(a,b,c);ins(b,a,c);
}
spfa(s);
int ans=inf;
for(int i=0;i<=k;i++)
ans=min(ans,d[t][i]);
printf("%d",ans);
return 0;
}