【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 }
完整代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }