[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
",mn);
40     return 0;
41 }
原文地址:https://www.cnblogs.com/HocRiser/p/9696241.html