发布于 

爬爬爬山

爬爬爬山

Wannafly Day 0 F

一道建图题。

题目来源:comet OJ

分析

这道题的主要难点在于如何建图(虽然也不是很难)。在题目给出的情况中,有n座山,和m条路,我们先把它们建成一个图。但是,我们可以发现我们还需要考虑“削山”的费用,那么,我们便可以把“削山”这个过程转化为一条边来处理。我们可以看出,wls的初始体力为\(k+hegiht[1]\),所以说所有途径的大于该高度的山都需要削。那么我们便可以将一座山分为两个点,一个只有入边,一个只有出边,然后将他们之间连上一条权值等于\(\max(0, (k+height[1]-height[i])^2)\)的边,然后跑一遍最短路即可。

虽然wls说这道题没卡SPFA,但是不知道为什么我的SPFA和Dijkstra都过不了。。。。最后只有加了LLL优化和读入优化之后SPFA才过。。。而且还比别人的慢。。。我现在已经严重怀疑我的指针写法的效率了。。。。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <iostream>
#include <algorithm>
#include <queue>

#define MAXN 100100
#define MAXM 200100
#define INF 0x3f3f3f3f3f3f3f3f

using namespace std;

struct Edge;

struct Node
{
Edge *edge;
long long high, dist;
bool flag;

Node()
{
high = 0;
flag = false;
dist = INF;
edge = NULL;
}
}node[2*MAXN];

struct Edge
{
Node *from, *to;
long long val;
Edge *next;

Edge(Node *from = NULL, Node *to = NULL, long long val = 0)
:from(from), to(to), val(val), next(from? from->edge: NULL) {}

};

long long n, m, k;

deque<Node*> q;
long long SPFA(Node *s, Node *t)
{
s->dist = 0;
s->flag = true;
q.push_back(s);

while (!q.empty())
{
Node *tmp = q.front();
q.pop_front();

for (Edge *e = tmp->edge; e; e = e->next)
{
if (tmp->dist + e->val < e->to->dist)
{
e->to->dist = tmp->dist + e->val;

// cout << e->to->high << " " << e->to->dist << endl;

if (!e->to->flag)
{
e->to->flag = true;
if ( (!q.empty()) && e->to->dist < q.front()->dist)
q.push_front(e->to);
else q.push_back(e->to);
}
}
}
tmp->flag = false;
}

return t->dist;
}

long long getlonglong()
{
long long x = 0;

char c = getchar();

while (c<'0' || c>'9')
c = getchar();

while (c<='9' && c>='0')
x = x * 10 + c - '0', c = getchar();

return x;
}

int main()
{
cin >> n >> m >> k;

for (long long i = 1; i<=n; i++)
{
node[i].high = getlonglong();
node[n+i].high = - node[i].high;
}

for (long long i = 1; i<=m; i++)
{
long long x, y, z;
x = getlonglong();
y = getlonglong();
z = getlonglong();

node[n+x].edge = new Edge(&node[n+x], &node[y], z);
node[n+y].edge = new Edge(&node[n+y], &node[x], z);
}

k += node[1].high;

for (long long i = 1; i<=n; i++)
{
long long x = max(node[i].high - k, 0LL);
node[i].edge = new Edge(&node[i], &node[n+i], x*x);
}

long long ans = SPFA(&node[1], &node[2*n]);

cout << ans << endl;
}

本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Songer](https://blog.songer.xyz/) 创建,使用 Stellar 作为主题。