[ACM][2018南京預賽]Magical Girl Haze

1、題面node

樣例輸入:spa

1
5 6 1
1 2 2
1 3 4
2 4 3
3 4 1
3 5 6
4 5 2code

樣例輸出:blog

3string

 

2、思路io

關鍵詞:分層BFS
class

考試時以爲題幹意思很清晰——求可將k條邊賦值爲0的最短路。起初幾個思路正確性均存疑,後來以爲應該要DP因而決定滯後了。。。im

正解——分層BFS,我的認爲思路與DP有些許相像,同時記錄節點及當前已賦值爲0的邊數,則在跑最短路時(這裏用的SPFA),可選擇是否將該條邊賦值爲0,當且僅當已選邊<k。next

 

3、代碼img

 1 #include <cstdio>
 2 #include <cstring> 
 3 
 4 #define MAXN 100005
 5 #define MAXM 200005
 6 #define MAXK 15
 7 #define INF 0x3f3f3f3f    
 8 
 9 int T, n, m, k, u, v, w, o, h[MAXN], d[MAXN][MAXK], vis[MAXN][MAXK];
10 
11 struct node {
12     int n, k;
13 } q[MAXN];
14 
15 struct edge {
16     int v, next, w;
17 } e[MAXM];
18 
19 void add(int u, int v, int w) {
20     o++, e[o] = (edge) {v, h[u], w}, h[u] = o;
21 }
22 
23 int spfa() {
24     int head = 1, tail = 2;
25     memset(d, INF, sizeof(d)), memset(vis, 0, sizeof(vis));
26     q[head] = (node) {1, 0}, d[1][0] = 0, vis[1][0] = 1;
27     while (head != tail) {
28         node o = q[head];
29         vis[o.n][o.k] = 0;
30         for (int x = h[o.n]; x; x = e[x].next) {
31             int v = e[x].v;
32             if (d[v][o.k] > d[o.n][o.k] + e[x].w) {
33                 d[v][o.k] = d[o.n][o.k] + e[x].w;
34                 if (!vis[v][o.k]) vis[v][o.k] = 1, q[tail++] = (node) {v, o.k};
35             }
36             if (o.k < k) {
37                 if (d[v][o.k + 1] > d[o.n][o.k]) {
38                     d[v][o.k + 1] = d[o.n][o.k];
39                     if (!vis[v][o.k + 1]) vis[v][o.k + 1] = 1, q[tail++] = (node) {v, o.k + 1};
40                 }
41             }
42         }
43         head++;
44     }
45     return d[n][k];
46 }
47 
48 int main() {
49     scanf("%d", &T);
50     for (int i = 1; i <= T; i++) {
51         o = 0, memset(h, 0, sizeof(h));
52         scanf("%d %d %d", &n, &m, &k);
53         for (int j = 1; j <= m; j++) scanf("%d %d %d", &u, &v, &w), add(u, v, w);
54         printf("%d\n", spfa()); 
55     }
56     return 0;
57 }

多個子問題着重考慮各類初始化!

相關文章
相關標籤/搜索