【题解】
设 d[i][j]为到达结点i,免费票用掉j张时,花费的最小值
则 d[i][j]可以更新 d[k][j] (i与k有边相连),若j<k,还可以更新 d[k][j+1]
注意总共会产生n*k=10^5种状态,SPFA算法,队列要开大一些,10^7可过,或者循环队列
还有SPFA会跑的很慢,"Spfa不适和分层图" ──贴吧
【代码】
#include<stdio.h>
#include<stdlib.h>
#define INF 1000000000
int d[10005][15],q[10000005],v[100005],w[100005],first[10005],next[100005],hash[1000020];
int e=0;
void tj(int x,int y,int z)
{
v[++e]=y;
w[e]=z;
next[e]=first[x];
first[x]=e;
}
int main()
{
int n,m,k,s,t,i,j,head=0,tail=1,x,y,z,ans=INF;
scanf("%d%d%d%d%d",&n,&m,&k,&s,&t);
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&x,&y,&z);
tj(x,y,z);
tj(y,x,z);
}
for(i=0;i<n;i++)
for(j=0;j<=k;j++)
d[i][j]=INF;
d[s][0]=0;
q[0]=s<<4;//编码 233
hash[s<<4]=1;
while(head<tail)
{
x=q[head]>>4;//解码 233
y=q[head]&15;
for(i=first[x];i!=0;i=next[i])
{
if(y<k)
if(d[v[i]][y+1]>d[x][y])
{
d[v[i]][y+1]=d[x][y];
z=v[i]<<4|y+1;//编码 233
if(hash[z]==0)
{
q[tail++]=z;
hash[z]=1;
}
}
if(d[v[i]][y]>d[x][y]+w[i])
{
d[v[i]][y]=d[x][y]+w[i];
z=v[i]<<4|y;
if(hash[z]==0)
{
q[tail++]=z;
hash[z]=1;
}
}
}
hash[q[head++]]=0;
}
for(i=0;i<=k;i++)
if(ans>d[t][i]) ans=d[t][i];
printf("%d",ans);
return 0;
}