题意:
有两种出行方式,一种是经济舱,一种是商务舱,商务舱比经济舱更加便捷。
一个人出行,想尽快达到目的地,但是他的钱不够,因此只能坐经济舱,但是幸运的是他有一张商务舱的票,意味着他可以选择坐一次商务舱,或者不坐(如果这样更省时间)。
给出地点数,起点,终点以及若干经济舱的线路和若干商务舱的线路,要求输出从起点到终点经过的点,以及是否使用了那张票,如果使用了,就输出使用的点,最后输出最短的时间。
思路:
首先不加商务舱的边,跑一次Dijkstra,求出不用票的最短时间;因为商务舱只能乘坐一次,而且K的值比较小,最大为1000,那么可以枚举每一条商务舱的边,每次加边,跑一次Dijkstra,求出最短时间,与不用票的最短时间进行比较,然后再把这条边去掉。
输出路径用两个fa数组记录前驱,递归输出路径。
代码:
1 #include <stdio.h> 2 #include <vector> 3 #include <queue> 4 #include <string.h> 5 using namespace std; 6 7 const int maxn = 505; 8 const int inf = 0x3f3f3f3f; 9 10 struct edge 11 { 12 int to,cost; 13 edge(int uu,int vv) 14 { 15 to = uu; 16 cost = vv; 17 } 18 }; 19 20 typedef pair<int,int> pii; 21 22 vector<edge> g[maxn]; 23 int d[maxn],dd[maxn],fa1[maxn],fa2[maxn]; 24 25 void adde(int st,int to,int cost) 26 { 27 g[st].push_back(edge(to,cost)); 28 } 29 30 void dijkstra(int s) 31 { 32 memset(d,inf,sizeof(d)); 33 memset(fa1,-1,sizeof(fa1)); 34 35 priority_queue<pii,vector<pii>,greater<pii> > pq; 36 37 d[s] = 0; 38 39 pq.push(pii(0,s)); 40 41 while (!pq.empty()) 42 { 43 pii x = pq.top();pq.pop(); 44 45 int v = x.second; 46 47 if (d[v] < x.first) continue; 48 49 for (int i = 0;i < g[v].size();i++) 50 { 51 edge e = g[v][i]; 52 53 if (d[e.to] > d[v] + e.cost) 54 { 55 d[e.to] = d[v] + e.cost; 56 pq.push(pii(d[e.to],e.to)); 57 fa1[e.to] = v; 58 } 59 } 60 } 61 } 62 63 int dijstra(int s) 64 { 65 memset(dd,inf,sizeof(dd)); 66 memset(fa2,-1,sizeof(fa2)); 67 68 priority_queue<pii,vector<pii>,greater<pii> > pq; 69 70 dd[s] = 0; 71 72 int use = -1; 73 74 pq.push(pii(0,s)); 75 76 while (!pq.empty()) 77 { 78 pii x = pq.top();pq.pop(); 79 80 int v = x.second; 81 82 //printf("%d %d** ",v,x.first); 83 84 85 if (dd[v] < x.first) continue; 86 87 for (int i = 0;i < g[v].size();i++) 88 { 89 edge e = g[v][i]; 90 91 //printf("%d %d** ",v,e.to); 92 93 if (dd[e.to] > dd[v] + e.cost) 94 { 95 //printf("%d %d** ",e.to,dd[e]); 96 97 dd[e.to] = dd[v] + e.cost; 98 pq.push(pii(dd[e.to],e.to)); 99 100 //printf("%d %d** ",dd[e.to],e.to); 101 102 if (dd[e.to] < d[e.to] && use == -1) 103 { 104 use = v; 105 } 106 107 fa2[e.to] = v; 108 } 109 } 110 } 111 112 return use; 113 } 114 115 void print1(int cur,int pre) 116 { 117 if (cur == -1) 118 { 119 return; 120 } 121 else 122 { 123 print1(fa1[cur],cur); 124 if (fa1[cur] == -1) printf("%d",cur); 125 else printf(" %d",cur); 126 } 127 } 128 129 void print2(int cur,int pre) 130 { 131 if (cur == -1) 132 { 133 return; 134 } 135 else 136 { 137 print2(fa2[cur],cur); 138 if (fa2[cur] == -1) printf("%d",cur); 139 else printf(" %d",cur); 140 } 141 } 142 143 144 int main() 145 { 146 int n,s,e; 147 148 int kase = 0; 149 150 while (scanf("%d%d%d",&n,&s,&e) != EOF) 151 { 152 if (kase++) printf(" "); 153 154 for (int i = 0;i <= n;i++) g[i].clear(); 155 156 int m; 157 158 scanf("%d",&m); 159 160 for (int i = 0;i < m;i++) 161 { 162 int x,y,z; 163 164 scanf("%d%d%d",&x,&y,&z); 165 166 adde(x,y,z); 167 adde(y,x,z); 168 } 169 170 dijkstra(s); 171 172 int ma = -1; 173 int ans = d[e]; 174 int xx,yy,zz; 175 176 int k; 177 178 scanf("%d",&k); 179 180 for (int i = 0;i < k;i++) 181 { 182 int x,y,z; 183 184 scanf("%d%d%d",&x,&y,&z); 185 186 adde(x,y,z); 187 adde(y,x,z); 188 189 dijstra(s); 190 191 g[x].pop_back(); 192 g[y].pop_back(); 193 194 //printf("%d %d** ",ans,dd[e]); 195 196 if (dd[e] < ans) 197 { 198 ans = dd[e]; 199 ma = i; 200 xx = x; 201 yy = y; 202 zz = z; 203 } 204 } 205 206 if (ma == -1) 207 { 208 print1(e,s); 209 printf(" "); 210 printf("Ticket Not Used "); 211 printf("%d ",d[e]); 212 } 213 else 214 { 215 adde(xx,yy,zz); 216 adde(yy,xx,zz); 217 218 int used = dijstra(s); 219 220 print2(e,s); 221 printf(" "); 222 printf("%d %d ",used,dd[e]); 223 } 224 } 225 226 return 0; 227 }