[ACM]Magical Girl Haze

一、题面

样例输入:

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

样例输出:

3

来源:ACM-ICPC 2018 南京赛区网络预赛

二、思路

关键词:分层BFS

考试时觉得题干意思很清晰——求可将k条边赋值为0的最短路。起初几个思路正确性均存疑,后来觉得应该要DP于是决定滞后了。。。

正解——分层BFS,个人认为思路与DP有些许相像,同时记录节点及当前已赋值为0的边数,则在跑最短路时(这里用的SPFA),可选择是否将该条边赋值为0,当且仅当已选边<k。

三、代码

 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 }

多个子问题着重考虑各种初始化!

猜你喜欢

转载自www.cnblogs.com/jinkun113/p/9579900.html