【Luogu P3371&P4779】【模板】单源最短路径(线段树优化Dijkstra)

线段树优化$\rm dijkstra$

线段树每个节点维护$[l,r]$中$dist$最小的点,删除则把该点$dist$赋值为$+\infty$,然后更新该点影响到的线段树上的其他节点即可。

可以得到“更新该节点影响到的线段树上的其他节点”部分的代码:
(线段树数组$\rm st[]$)

 1 void pushup(int x) {
 2     st[x] = dist[st[x << 1]] < dist[st[x << 1 | 1]] ? st[x << 1] : st[x << 1 | 1];
 3 }
 4 
 5 void updata(int x, int l, int r, int q) {  //更新信息
 6     if(l != r) {
 7         int mid = (l + r) >> 1;
 8         if(q <= mid) updata(x << 1, l, mid, q);
 9         else updata(x << 1 | 1, mid + 1, r, q);
10         pushup(x);
11     }
12 }


然后$\rm dijkstra$代码如下:

 1 //此处ans为最终数组
 2 void dijkstra(int s) {
 3     ans[s] = dist[s] = 0;
 4     build(1, 1, n);  //建树
 5     while(dist[st[1]] < inf) {
 6         int v = st[1]; vis[v] = 1; //取出最小的
 7         for(int i = head[v]; i != -1; i = edges[i].nxt) if(!vis[edges[i].to]) { //更新相邻节点
 8             dist[edges[i].to] = min(dist[edges[i].to], dist[v] + edges[i].val);//修改dist
 9             updata(1, 1, n, edges[i].to);//更新所影响的节点
10         }
11         ans[v] = dist[v]; dist[v] = inf;//记录答案,删除节点
12         updata(1, 1, n, v);  //更新所影响的节点
13     }
14 }

 

完整代码:

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int MAXN = 1e5 + 5, inf = 0x3f3f3f3f;
 6 
 7 int st[MAXN << 3], head[MAXN], dist[MAXN], ans[MAXN], n, m, cnt = 0;
 8 bool vis[MAXN];
 9 
10 struct edge {
11     int to, nxt, val;
12 } edges[MAXN << 1];
13 
14 void addedge(int from, int to, int val) {
15     edges[cnt].to = to, edges[cnt].val = val;
16     edges[cnt].nxt = head[from]; head[from] = cnt++;
17 }
18 
19 void pushup(int x) {
20     st[x] = dist[st[x << 1]] < dist[st[x << 1 | 1]] ? st[x << 1] : st[x << 1 | 1];
21 }
22 
23 void build(int x, int l, int r) {
24     if(l < r) {
25         int mid = (l + r) >> 1;
26         build(x << 1, l, mid);
27         build(x << 1 | 1, mid + 1, r);
28         pushup(x);
29     } else st[x] = l;
30 }
31 
32 void updata(int x, int l, int r, int q) {
33     if(l != r) {
34         int mid = (l + r) >> 1;
35         if(q <= mid) updata(x << 1, l, mid, q);
36         else updata(x << 1 | 1, mid + 1, r, q);
37         pushup(x);
38     }
39 }
40 
41 void dijkstra(int s) {
42     ans[s] = dist[s] = 0;
43     build(1, 1, n);
44     while(dist[st[1]] < inf) {
45         int v = st[1]; vis[v] = 1;
46         for(int i = head[v]; i != -1; i = edges[i].nxt) if(!vis[edges[i].to]) {
47             dist[edges[i].to] = min(dist[edges[i].to], dist[v] + edges[i].val);
48             updata(1, 1, n, edges[i].to);
49         }
50         ans[v] = dist[v]; dist[v] = inf;
51         updata(1, 1, n, v);
52     }
53 }
54 
55 int main() {
56     ios::sync_with_stdio(false);
57     memset(dist, 0x3f, sizeof(dist));
58     memset(head, 0xff, sizeof(head));
59     memset(ans, 0x3f, sizeof(ans));
60     int u, v, w, s;
61     cin >> n >> m >> s;
62     for(int i = 0; i < m; i++) {
63         cin >> u >> v >> w;
64         addedge(u, v, w);
65     }
66     dijkstra(s);
67     for(int i = 1; i <= n; i++) cout << ans[i] << " ";
68     cout << endl;
69     return 0;
70 }
View Code

 

posted @ 2018-08-17 10:44  zhylj  阅读(305)  评论(0编辑  收藏  举报