P10480 可达性统计(拓扑,bitset 优化)
从数的角度来看,如果知道任意一个点能到达的点的数量,那么它的前驱节点一定也能到达,但是,只累加数的话无法处理可能存在重合点的情况。
所以,考虑从集合的角度,设
如果
在 DAG 里边,我们可以先跑个拓扑序出来,从后往前处理
时间复杂度呢 ... 我觉得可以从每个点的贡献角度想,
访问集合中的每个点时间贡献为
累加起来就是
考虑位运算优化,也就是状态压缩的思想
这里有个很冷门?的工具 bitset<N>
,表示一个 N 位的二进制数,每八位占用一个字节,
而我们知道一个 int 变量是有
那么 N 位的 bitset 执行一次位运算的复杂度就为
所以所以,每个集合
#include <bits/stdc++.h> #define re register int using namespace std; const int N = 3e4 + 10; struct Edge { int to, next; }e[N]; int top, h[N], in[N]; int n, m; vector<int> seq; bitset<N> f[N]; inline void add(int x, int y) { e[++ top] = (Edge){y, h[x]}; h[x] = top; } inline void topsort() { queue<int> q; for (re i = 1; i <= n; i ++) if (in[i] == 0) q.push(i); while (!q.empty()) { int x = q.front(); q.pop(); seq.push_back(x); for (re i = h[x]; i; i = e[i].next) { int y = e[i].to; if (-- in[y] == 0) q.push(y); } } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m; while (m --) { int x, y; cin >> x >> y; add(x, y); in[y] ++; } topsort(); for (re i = seq.size() - 1; i >= 0; i --) { int u = seq[i]; f[u][u] = 1; for (re j = h[u]; j; j = e[j].next) { int v = e[j].to; f[u] |= f[v]; } } for (re i = 1; i <= n; i ++) cout << f[i].count() << '\n'; //bitset成员函数,返回有多少位是 1 return 0; }
分类:
C 图论 - 拓扑排序
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析