题意
给出若干个城市,城市和城市存在修好的道路,和存在一些没有修好的道路。要求你求出最多修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 }