不错的最短路题.一开始没想到如何处理 "Mario NEVER super runs through a Castle" 这个条件,然后大力分类讨论.
在写了将近70行的状态扩展后,我放弃了.
实际上,这题没有这么麻烦.这个条件限制只用在floyd预处理的时候就可以解决了.
具体来说, 在floyd的时候,限制中转点为乡村
for(int k = 1; k <= A; k++) for(int i = 1; i <= (A + B); i++) for(int j = 1; j <= (A + B); j++)
根据算法的性质, 这样所有路径除起点, 终点之外的点就都在乡村了.
用了这个非常妙的做法以后, 就不难写出状态的扩展了.
这里用的是dijkstra
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 using namespace std; 8 const int MAXN = 1e2 + 20; 9 const int INF = 0x3f3f3f3f; 10 11 int A, B, M, L, K; 12 int d[MAXN][MAXN], f[MAXN][12]; 13 bool vis[MAXN][12]; 14 15 struct edge 16 { 17 int to, cost; 18 };vector<edge> g[MAXN]; 19 struct state 20 { 21 int pos, time, k; 22 state(int u = 0, int t = 0, int k = 0) : 23 pos(u), time(t), k(k) {} 24 bool operator >(const state &rhs) const{ 25 return time > rhs.time; 26 } 27 }; 28 29 void init() 30 { 31 memset(d, 0x3f, sizeof(d)); 32 memset(f, 0x3f, sizeof(f)); 33 memset(vis, false, sizeof(vis)); 34 for(int i = 1; i <= (A + B); i++) g[i].clear(); 35 } 36 37 void floyd() 38 { 39 for(int i = 1; i <= (A + B); i++) d[i][i] = 0; 40 for(int k = 1; k <= A; k++) 41 for(int i = 1; i <= (A + B); i++) 42 for(int j = 1; j <= (A + B); j++) 43 if(d[i][k] != INF && d[k][j] != INF) 44 d[i][j] = min(d[i][j], d[i][k] + d[k][j]); 45 } 46 47 inline bool tension(const int &st, int &lg) 48 { 49 return st < lg ? (lg = st, true) : false; 50 } 51 52 int bfs() 53 { 54 priority_queue<state, vector<state>, greater<state> > q; 55 f[(A + B)][0] = 0; 56 q.push(state((A + B), 0, 0)); 57 58 while(!q.empty()) 59 { 60 state u = q.top(); q.pop(); 61 if(u.pos == 1) return u.time; 62 if(vis[u.pos][u.k]) continue; 63 vis[u.pos][u.k] = true; 64 for(int i = 0; i < (int) g[u.pos].size(); i++) 65 { 66 edge &e = g[u.pos][i]; 67 if(tension(u.time + e.cost, f[e.to][u.k])) 68 q.push(state(e.to, f[e.to][u.k], u.k)); 69 } 70 71 if(u.k < K) 72 for(int i = 1; i <= (A + B); i++) 73 if(d[i][u.pos] <= L && tension(u.time + 0, f[i][u.k + 1])) 74 q.push(state(i, f[i][u.k + 1], u.k + 1)); 75 } 76 return rand(); 77 } 78 79 int main() 80 { 81 //freopen("10269.in", "r", stdin); 82 //freopen("10269.out", "w", stdout); 83 int T; cin>>T; 84 while(T--) 85 { 86 cin>>A>>B>>M>>L>>K;init(); 87 for(int i = 1, u, v, c; i <= M; i++) 88 { 89 scanf("%d%d%d", &u, &v, &c); 90 d[u][v] = d[v][u] = c; 91 g[u].push_back((edge){v, c}); 92 g[v].push_back((edge){u, c}); 93 } 94 floyd(); 95 printf("%d ", bfs()); 96 } 97 return 0; 98 }