BZOJ 5097: [Lydsy1711月赛]实时导航(最短路 + bitset)

题意

n 个点的有向图,边权 {1,2,3,4}m 次修改边权/加边/删边,q 次询问:以 si 为起点,输出它到其他点的最短路。

n5×102,m5×104,q5×103

题解

这图很密,如果修改就做一遍 DijsktraO((n+m)logn) 的复杂度,显然是过不去的。

但是发现边权似乎不大,我们考虑把这些要进来的点压到 std :: bitset<N> 里面。

也就是我们维护到当前距离为 1,2,3,4 的队列,然后我们把图也可以用 std :: bitset<N> 存下来。

然后每次就把要进来的点 或(or)上当前维护队列就行了,每次就循环移位就可以了。

然后每次取 std :: bitset<N> 的元素就行了,这里有两个骚操作 _Find_first() 以及 _Find_next(u) ,可以快速查找 std :: bitset<N> 的元素。

最后复杂度就是 O(qn2ω+m) 的,看起来很科学qwq

总结

对于稠密图,可以考虑用 std :: bitset 来优化复杂度,加快暴力操作。

然后对于边权小,可以考虑用普通队列来替代优先队列,常常会得到更优秀的复杂度。

代码

具体看代码操作就行了。

/************************************************************** Problem: 5097 User: zjp_shadow Language: C++ Result: Accepted Time:10624 ms Memory:2440 kb ****************************************************************/ #include <bits/stdc++.h> #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i) #define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i) #define Set(a, v) memset(a, v, sizeof(a)) #define Cpy(a, b) memcpy(a, b, sizeof(a)) #define debug(x) cout << #x << ": " << (x) << endl #define DEBUG(...) fprintf(stderr, __VA_ARGS__) using namespace std; template<typename T> inline bool chkmin(T &a, T b) {return b < a ? a = b, 1 : 0;} template<typename T> inline bool chkmax(T &a, T b) {return b > a ? a = b, 1 : 0;} inline int read() { int x(0), sgn(1); char ch(getchar()); for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1; for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48); return x * sgn; } void File() { #ifdef zjp_shadow freopen ("5097.in", "r", stdin); freopen ("5097.out", "w", stdout); #endif } const int N = 510; int val[N][N]; typedef bitset<N> Info; Info G[N][4]; int dis[N], que[N], len, n, m; void Bfs(int S) { Info Q[4]; For (i, 0, 3) Q[i] = G[S][i]; Set(dis, 0); dis[S] = -1; for (int cur = 0, tim = 1, o = 0; cur < 5; ++ tim, o = (o + 1) % 4) { len = 0; for (int v = Q[o]._Find_first(); v < (int)Q[o].size(); v = Q[o]._Find_next(v)) { Q[o][v] = false; if (!dis[v]) que[++ len] = v; } For (i, 1, len) { int u = que[i]; dis[u] = tim; Q[(o + 1) % 4] |= G[u][0]; Q[(o + 2) % 4] |= G[u][1]; Q[(o + 3) % 4] |= G[u][2]; Q[o] |= G[u][3]; } cur = !len ? cur + 1 : 0; } int ans = 0; For (i, 1, n) if (i != S) ans += i * dis[i]; printf ("%d\n", ans); } int main () { File(); n = read(); m = read(); For (i, 1, n) For (j, 1, n) { int w = read(); val[i][j] = w; if (w) G[i][w - 1][j] = true; } For (i, 1, m) { char opt[5]; scanf ("%s", opt + 1); if (opt[1] == 'Q') Bfs(read()); else { int u = read(), v = read(), w = read(); if (val[u][v]) G[u][val[u][v] - 1][v] = false; val[u][v] = w; if (w) G[u][w - 1][v] = true; } } return 0; }

__EOF__

本文作者zjp_shadow
本文链接https://www.cnblogs.com/zjp-shadow/p/9765417.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zjp_shadow  阅读(203)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示