1. 程式人生 > >[BZOJ2763][JLOI2011]飛行路線(分層圖最短路)

[BZOJ2763][JLOI2011]飛行路線(分層圖最短路)

div 宋體 define struct 所有 void code printf string

求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 }

[BZOJ2763][JLOI2011]飛行路線(分層圖最短路)