分层最短路
问题
给一个图,有k次机会可以通过一条边而不计算其权值,问从起点到终点权值和最少为多少?
思路
核心思路:动态规划.把图中的每一个点拆成k+1种状态,分别是从0....k,表示用了多少次不计边权的机会,然后从起点开始跑最短路.设dp[i][j]为起点到i点用了j次机会的最短距离,当更新到dp[i][j]时,先遍历连接i点的所有边,然后对于每条边又两种情况,用一次机会或者不用,不用的话会有if(dp[to][j]>dp[i][j]+cost) dp[to][j]=dp[i][j]+cost..,用的话会有if(dp[to][j+1]>dp[i][j]) dp[to][j+1]=dp[i][j]...最后答案就是dp[t][k],t为终点.由于分层图需要一层一层的跑,所以SPFA会比dijkstra快.
代码
1 struct P 2 { 3 int s,k,d; 4 P (){} 5 P (int s_,int k_,int d_){s=s_,k=k_,d=d_;}; 6 }; 7 struct edge{int to,cost;}; 8 vector<edge> es[MAX]; 9 int dp[MAX][MAX]; 10 int n,m,S,T,K; //n¸öµã,mÌõ±ß,S,TΪÆðµãÖÕµã,K×î¶àÓÉK´Î»ú»á 11 12 void init(int n) 13 { 14 for(int i=1;i<=n;i++) 15 for(int j=0;j<=K;j++) 16 if(i!=S) dp[i][j]=INF; 17 else dp[i][j]=0; 18 } 19 20 void SPFA() 21 { 22 init(n); 23 queue<P> que; 24 que.push(P(S,0,0)); 25 while(que.size()) 26 { 27 P p=que.front();que.pop(); 28 if(p.d>dp[p.s][p.k]) continue; 29 for(int i=0;i<es[p.s].size();i++) 30 { 31 edge e=es[p.s][i]; 32 if(dp[e.to][p.k]>dp[p.s][p.k]+e.cost) 33 { 34 dp[e.to][p.k]=dp[p.s][p.k]+e.cost; 35 que.push(P(e.to,p.k,dp[e.to][p.k])); 36 } 37 if(p.k<K&&dp[e.to][p.k+1]>dp[p.s][p.k]) 38 { 39 dp[e.to][p.k+1]=dp[p.s][p.k]; 40 que.push(P(e.to,p.k+1,dp[e.to][p.k+1])); 41 } 42 } 43 } 44 }