可达性统计
原题链接:可达性统计
题目大意
给你一张\(n\)个点\(m\)条边的有向无环图,分别统计从每个点出发能够到达的点的数量
题目题解
看到题意就知道要用到拓扑排序,但是拓扑排序的理论复杂度在30000的极限条件下会超时,这个时候我们考虑使用 \(bitset\),一个很好用的代替bool的防卡常技巧,详细的说明这里不说,可以去百度上查看相关运用
//#define fre yes #include <queue> #include <bitset> #include <cstdio> #include <cstring> #include <algorithm> const int N = 30005; int head[N << 1], to[N << 1], ver[N << 1]; int in[N], ans[N]; std::bitset<N> f[N]; int tot, k; void addedge(int x, int y) { ver[tot] = y; to[tot] = head[x]; head[x] = tot++; } int n, m; void toposort() { std::queue<int> q; for (int i = 1; i <= n; i++) { if(!in[i]) q.push(i); } while(!q.empty()) { int t = q.front(); q.pop(); ans[++k] = t; for (int i = head[t]; ~i; i = to[i]) { int v = ver[i]; in[v]--; if(!in[v]) q.push(v); } } } int main() { memset(head, -1, sizeof(head)); scanf("%d %d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d %d", &u, &v); addedge(u, v); in[v] ++; } toposort(); // for (int i = 1; i <= n; i++) { // printf("%d ", ans[i]); // } for (int i = n; i >= 1; i--) { int j = ans[i]; f[j][j] = 1; for (int x = head[j]; ~x; x = to[x]) { f[j] |= f[ver[x]]; } } for (int i = 1; i <= n; i++) { printf("%d\n", f[i].count()); } return 0; }