[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 }

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

原文地址:https://www.cnblogs.com/jinkun113/p/9579900.html

时间: 2024-10-11 10:31:43

[ACM]Magical Girl Haze的相关文章

ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze

262144K There are NN cities in the country, and MM directional roads from uu to v(1\le u, v\le n)v(1≤u,v≤n). Every road has a distance c_ici?. Haze is a Magical Girl that lives in City 11, she can choose no more than KK roads and make their distances

【分层最短路】Magical Girl Haze

https://nanti.jisuanke.com/t/31001 有K次机会可以让一条边的权值变为0,求最短路. 在存储单源最短路的数组上多开一维状态,d[i][k]表示走到序号i的点,且让k条边权值为0时的最短路. 对于每个待更新的点,尝试不置零此边的状态和置零此边的状态,分别压入优先队列去更新其他状态. 另外,此题由于有重边,需要先去重,保留同起始点最短的边. 代码: #include <iostream> #include <algorithm> #include <

Magical Girl Haze 南京网络赛2018

题意: 就是使不大于k条路的权值变为零后求最短路 解析: d[i][j]表示使j条路变为权值后从起点到点i的最短路径 这题不能用spfa做  tle #include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <cctype> #include <set> #include <v

2018icpc南京网络赛-L Magical Girl Haze (分层图最短路)

题意: 有向图,可以把k条路的长度变为0,求1到n的最短路 思路: 将图复制k份,一共k+1层图,对于每一条i→j,都连一条低层的i→高层的j,并且权值为0 即对每一对<i,j,w>,都加边<i,j,w>,<i+n,j+n,w>,<i+2n,j+2n,w>,....,<i+kn,j+kn,w> 同时加“楼梯”<i,j+n,0>,<i+n,j+2n,0>,...,<i+(k-1)n, j+kn> 然后跑一个1~(

计蒜客 31001 - Magical Girl Haze - [最短路][2018ICPC南京网络预赛L题]

题目链接:https://nanti.jisuanke.com/t/31001 题意: 一带权有向图,有 n 个节点编号1~n,m条有向边,现在一人从节点 1 出发,他有最多 k 次机会施展魔法使得某一条边的权变成 0,问他走到节点 n 的最小权值为多少. 题解: 将dist数组和vis数组都扩展一维: dist[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离: vis[c][i]代表:已经使用了 c 次变0魔法后,走到节点 i 的最短距离,这个最短距离是否已经被准确计算

ACM-ICPC 2018 南京赛区网络预赛 L. Magical Girl Haze(分层dijkstra)

题意:有n个地方,m条带权值的路,你有k次机会将一条路的权值变为0,求1到n的最短距离. 分析:这是一题分层dijkstra的模板题,因为k的大小不是很大,最坏的情况也就是10,而我们一般的最短路问题只是建一个平面的图. 而分层dijkstra是一个空间的.怎么操作呢? 举个简单的栗子 当数据如下是 n  m  k 3  2  1 1  2  5(路的起点1,终点2,权值5) 2  3  6 没有k的情况就是这样的 如果有k的情况,即1到2权值可能为0,2到3也可能为0,我们可以加一个平面表示他

ICPC 2018 南京网络赛 J Magical Girl Haze(多层图最短路)

传送门:https://nanti.jisuanke.com/t/A1958 题意:n个点m条边的路,你有k次机会将某条路上的边权变为0,问你最短路径长度 题解:最短路变形,我们需要在常规的最短路上多开 一维,记录,我消耗j次机会时的最短路径长度为多少 代码: /** * ┏┓ ┏┓ * ┏┛┗━━━━━━━┛┗━━━┓ * ┃ ┃ * ┃ ━ ┃ * ┃ > < ┃ * ┃ ┃ * ┃... ⌒ ... ┃ * ┃ ┃ * ┗━┓ ┏━┛ * ┃ ┃ Code is far away fro

2018 ACM 网络选拔赛 南京赛区

A. An Olympian Math Problem 1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <time.h> 6 #include <string> 7 #include <set> 8 #include <map> 9 #include <list>

ACM-ICPC 2018南京赛区网络预选赛

A题:An Olympian Math Problem 可以发现最终的答案就是n-1 1 #include <iostream> 2 #include<bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 int main() 6 { 7 int t; 8 ll n; 9 scanf("%d",&t); 10 while(t--) 11 { 12 scanf("%lld&