[BZOJ2763][JLOI2011]飞行路线(分层图最短路)
求S到T的最短路,中间最多k条边可以不计代价。
显然可以f[i][j]表示当前在点i,已有j条边不计代价的最小代价,SPFA解决。
NOI2018后显然不能写SPFA,考虑为所有i+j*n都建一个点,Dijkstra即可。
这种Dij代替SPFA跑DP的方法就叫分层图最短路。
1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 #include<algorithm> 5 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 6 using namespace std; 7 8 const int N=220010,inf=1e9; 9 bool b[N]; 10 int n,m,k,S,T,u,v,w,cnt,dis[N],h[N],to[N],val[N],nxt[N]; 11 struct P{ int x,d; }; 12 bool operator <(const P &a,const P &b){ return a.d>b.d; } 13 priority_queue<P>Q; 14 void add(int u,int v,int w){ to[++cnt]=v; val[cnt]=w; nxt[cnt]=h[u]; h[u]=cnt; } 15 16 void Dij(){ 17 rep(i,1,(k+1)*n) dis[i]=inf; dis[S]=0; Q.push((P){S,0}); 18 while (!Q.empty()){ 19 int s=Q.top().x,x=(s-1)%n+1; Q.pop(); 20 if (b[s]) continue; b[s]=1; 21 for (int i=h[x],k; i; i=nxt[i]){ 22 k=to[i]; int p=s-x+k+n; 23 if (p<=(k+1)*n && !b[p] && dis[p]>dis[s]) 24 dis[p]=dis[s],Q.push((P){p,dis[p]}); 25 p=s-x+k; 26 if (!b[p] && dis[p]>dis[s]+val[i]) 27 dis[p]=dis[s]+val[i],Q.push((P){p,dis[p]}); 28 } 29 } 30 } 31 32 int main(){ 33 freopen("bzoj2763.in","r",stdin); 34 freopen("bzoj2763.out","w",stdout); 35 scanf("%d%d%d%d%d",&n,&m,&k,&S,&T); S++; T++; 36 rep(i,1,m) scanf("%d%d%d",&u,&v,&w),u++,v++,add(u,v,w),add(v,u,w); 37 Dij(); int mn=inf; 38 rep(i,0,k) mn=min(mn,dis[T+i*n]); 39 printf("%d\n",mn); 40 return 0; 41 }