堆优化dij
- Dijkstra基于贪心思想,指适用为边权都是非负数的图
- 而且这样写不能用于求最长路,需要进行优化,求最长路可以用SPFA
-
最长路没有子结构,子段最长不一定总的最长。如图:
-
code
priority_queue< pair<int, int> > q; //这里两个'>'尽量不要写在一起,有的编译环境会CE int d[N]; bool v[N]; void dij(int u) { memset(v, 0, sizeof(v)); memset(d, 0x3f, sizeof(d)); d[u] = 0; q.push(make_pair(0, u)); while (!q.empty()) { int x = q.top().second; q.pop(); if (v[x]) continue; v[x] = 1; for(int i = head[x]; i; i = e[i].next) { int y = e[i].t; if (d[y] > d[x] + e[i].d) { d[y] = d[x] + e[i].d; q.push(make_pair(-d[y], y)); //默认是从大到小排序,变成负数后就是从小到大了 } } } }
-
spfa
- SPFA在随机图上时间效率为(O(km))级别, 其中(k)是个较小的常数
但在特殊构造的图上,可能会退化为(O(nm)),必须谨慎使用code
queue<int> q; void Spfa(int u) { memset(d, 0x3f, sizeof(d)); d[u] = 0; q.push(u); v[u] = 1; while (!q.empty()) { int x = q.front(); q.pop(); v[x] = 0; for (int i = head[x]; i; i = e[i].next) { int y = e[i].t; if (d[y] > d[x] + e[i].d) { d[y] = d[x] + e[i].d; if (v[y]) continue; q.push(y); v[y] = 1; } } } }
- SPFA还可以通过双端队列进行SLF优化(改变的地方我都有标注)
- ‘code’
deque<int> q; void Spfa(int u) { memset(d, 0x3f, sizeof(d)); d[u] = 0; q.push_back(u); v[u] = 1;//这里 while (!q.empty()) { int x = q.front(); q.pop_front(); v[x] = 0;//这里 for (int i = head[x]; i; i = e[i].next) { int y = e[i].t; if (d[y] > d[x] + e[i].d) { d[y] = d[x] + e[i].d; if (v[y]) continue; if (d[y] <= d[q.front()]) q.push_front(y); //这里是最主要的地方,加入的元素如果比队首小,就放在队首 else q.push_back(y); //这里 v[y] = 1; } } } }
- ‘code’