【题解】
设 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; }