抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

听说 zkw 线段树优化 dijkstra 跑得很快呢,洛谷最优解都是用这个的。

然后我就自己打了一发。

确实快了许多,但还是被最优解吊着打……

但至少能过bzoj3040

把普通堆优 dij 的堆改成线段树就可以了。

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
struct Edge
{
int to, dist, nxt;
} e[maxm << 1];

int first[maxn];

inline void add_edge(int from, int to, int dist)
{
static int cnt = 0;
e[++cnt].nxt = first[from];
first[from] = cnt;
e[cnt].dist = dist;
e[cnt].to = to;
}

int dist[maxn];

struct DIJKSTRA
{
#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
struct Tree
{
int no[maxn << 2];
int t;

inline void build_tree()
{
for(t = 1; t <= n; t <<= 1);
for(register int i = 1; i <= n; ++i)
no[i + t] = i;
}

inline void change(int k)
{
for(k += t, k >>= 1; k; k >>= 1)
no[k] = dist[no[ls(k)]] < dist[no[rs(k)]]
? no[ls(k)] : no[rs(k)];
}

inline void del(int k)
{
for(no[k += t] = 0, k >>= 1; k; k >>= 1)
no[k] = dist[no[ls(k)]] < dist[no[rs(k)]]
? no[ls(k)] : no[rs(k)];
}
} tr;

inline void dijkstra(int s)
{
memset(dist, 0x3f, sizeof(dist));
dist[s] = 0;
tr.build_tree();
tr.change(s);
for(int i = 1; i <= n; ++i)
{
register int now = tr.no[1];
if(!now || dist[now] >= inf)
break;
tr.del(now);
for(int j = first[now]; j; j = e[j].nxt)
{
register int to = e[j].to;
if(dist[to] > dist[now] + e[j].dist)
{
dist[to] = dist[now] + e[j].dist;
tr.change(to);
}
}
}
}
}

评论