Lightoj 1281 New Traffic System (记忆化Dijkstra)

题意

给出若干个城市,城市和城市存在修好的道路,和存在一些没有修好的道路。要求你求出最多修d条路,求起点s到终点t的最短路径是 多少。
给出城市数量n,城市编号从0 ~ n - 1 . n < 1e4 .
给出修好的道路的条数m, 2 <= m <= 3 * 1e4 .
给出存在但未被修好的路的条数k , 1 <= k <= 1e4 .
最多修d条路, 0 <= d <= 10 .
求s城市到t城市的最多修d条路的情况下的最短路.

分析

考虑dijkstra算法,朴素的没有条件的求最短路,只要从起点拓展即可。这里要求中途可以修路,相当于我们多了一维进行更新。
dp[i][j] 表示到达i城市,已经修了j条路的时候的最短路径长度。

仍然用优先队列进行维护,每次取出最小的dp[i][j](前提是在队列里)。然后更新周围的节点。

注意点就是这个图是有向图,一开始当作无向图压了两次边导致了WA。

题目中有说from a to b 的都是有方向的,如果是无方向的话,题目应当描述成 between a and b.

代码

  1 #define rep(x,y,z) for(int x=y;x<z;x++)
  2 #define drep(x,y,z) for(int x=y;x>=z;x--)
  3 #define pb(x) push_back(x)
  4 #define mp(x,y) make_pair(x,y)
  5 #define fi first
  6 #define se second
  7 
  8 #include <iostream>
  9 #include <stdio.h>
 10 #include <string.h>
 11 #include <algorithm>
 12 #include <vector>
 13 #include <queue>
 14 using namespace std;
 15 
 16 const int N = 1e4 + 10;
 17 const int D = 15;
 18 const int inf = 0x3f3f3f3f;
 19 
 20 int dp[N][D];
 21 bool mark[N][D];
 22 vector<pair<int,int> > ori[N];
 23 vector<pair<int,int> > cho[N];
 24 struct box{
 25     int pos , use , cost;
 26     box(){}
 27     box(int a , int b , int c){pos=a,use=b,cost=c;}
 28     bool operator < (const box & A) const {
 29         return cost > A.cost;
 30     }
 31 };
 32 
 33 void init(){
 34     rep(i,0,N){ori[i].clear();cho[i].clear();}
 35     memset(dp,inf,sizeof(dp));
 36     memset(mark,0,sizeof(mark));
 37 }
 38 
 39 int slove(int n ,int d){
 40     //
 41     dp[0][0] = 0;
 42     priority_queue<box> Q;
 43     Q.push(box(0,0,dp[0][0]));
 44     while(!Q.empty()){
 45         int pos = Q.top().pos;
 46         int use = Q.top().use;
 47         Q.pop();
 48         if(mark[pos][use]) continue;
 49         mark[pos][use] = 1;
 50         //
 51         //cout << pos << " " << use << " " << dp[pos][use] << endl;
 52         //debug
 53         if(pos == n - 1) break;
 54         //
 55         int osize = ori[pos].size();
 56         int csize = cho[pos].size();
 57         //
 58         rep(i,0,osize){
 59             int aim = ori[pos][i].fi , w = ori[pos][i].se;
 60             if(dp[aim][use] > dp[pos][use] + w){
 61                 dp[aim][use] = dp[pos][use] + w;
 62                 Q.push(box(aim,use,dp[aim][use]));
 63             }
 64         }
 65         if(use + 1 > d) continue;
 66         rep(i,0,csize){
 67             int aim = cho[pos][i].fi , w = cho[pos][i].se;
 68             if(dp[aim][use + 1] > dp[pos][use] + w){
 69                 dp[aim][use + 1] = dp[pos][use] + w;
 70                 Q.push(box(aim,use+1,dp[aim][use + 1]));
 71             }
 72         }
 73     }
 74     //
 75     int ans = inf;
 76     rep(i,0,d+1){ans = min(ans,dp[n-1][i]);}
 77     //
 78     return ans == inf ? -1 : ans;
 79 }
 80 
 81 int main(){
 82     int t;
 83     scanf("%d",&t);
 84     rep(tt,1,t+1){
 85         init();
 86         int n , m , k , d;
 87         scanf("%d %d %d %d",&n,&m,&k,&d);
 88         rep(i,0,m){
 89             int a , b , d;
 90             scanf("%d %d %d",&a,&b,&d);
 91             ori[a].pb(mp(b,d));
 92             //ori[b].pb(mp(a,d));
 93         }
 94         rep(i,0,k){
 95             int a , b , d;
 96             scanf("%d %d %d",&a,&b,&d);
 97             cho[a].pb(mp(b,d));
 98             //cho[b].pb(mp(a,d));
 99         }
100         int ans = slove(n,d);
101         //
102         printf("Case %d: ",tt);
103         if(ans < 0) puts("Impossible");
104         else printf("%d
",ans);
105     }
106     return 0;
107 }
原文地址:https://www.cnblogs.com/ticsmtc/p/6105109.html