分层最短路

问题

给一个图,有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 }

 

posted @ 2019-07-28 14:03  VBL  阅读(142)  评论(0编辑  收藏  举报