我会说这是太神给NOIP入门的同学出的题么?!表示今天刚做,虽然以前学过,但这是第一次写,要注意建边的时候只需要建一层的就可以了,然后每次跑spfa的时候,看看能不能跑到下一层。
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 200010 #define inf 1000000000 #define maxm 200010 using namespace std; int next[maxm],to[maxm],len[maxm],head[maxn]; int dis[maxn],q[maxn]; bool vis[maxn]; int n,m,T,k,s,t,num; int cal(int x,int y) { return x+y*n; } void addedge(int x,int y,int z) { num++;to[num]=y;len[num]=z;next[num]=head[x];head[x]=num; } void spfa() { for (int i=0;i<=cal(n,k);i++) dis[i]=inf; int l=0,r=1; dis[s]=0;q[1]=s;vis[s]=1; while (l!=r) { l++;if (l==maxn) l=0; int x=q[l]; int d=x/n,t=x%n; for (int p=head[t];p;p=next[p]) { if (dis[cal(to[p],d)]>dis[cal(t,d)]+len[p]) { dis[cal(to[p],d)]=dis[cal(t,d)]+len[p]; if (!vis[cal(to[p],d)]) { vis[cal(to[p],d)]=1; r++;if (r==maxn) r=0; q[r]=cal(to[p],d); } } if (d<k && dis[cal(t,d)]<dis[cal(to[p],d+1)]) { dis[cal(to[p],d+1)]=dis[cal(t,d)]; if (!vis[cal(to[p],d+1)]) { vis[cal(to[p],d+1)]=1; r++;if (r==maxn) r=0; q[r]=cal(to[p],d+1); } } } vis[x]=0; } } int main() { scanf("%d%d%d%d%d",&n,&m,&k,&s,&t); for (int i=1;i<=m;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); addedge(x,y,z);addedge(y,x,z); } spfa(); printf("%d\n",dis[cal(t,k)]); return 0; }