闭包传递
https://ac.nowcoder.com/acm/contest/1013/A
题面
给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量。\(N,M\leq 30000\)
分析
用\(bitset\)维护每个点的闭包
时间复杂度\(O(\frac{n\times n}{30})\)
\(\therefore\) 30000级别很有可能是闭包(\(lg^4\))
bitset
bitset操作:
- 调用一位:s[]
- 二进制操作:^|&
- 判断是否相等:== !=
- 设1: s.set();
- 设0:s.reset();
- 统计1个数:s.count();
#include<bits/stdc++.h>
using namespace std;
const int N=3e4+5;
int n,m,to[N],nxt[N],he[N],cnt;
bool fl[N];
bitset<N>b[N];
inline void add(int u,int v) {
to[++cnt]=v,nxt[cnt]=he[u],he[u]=cnt;
}
void dfs(int u) {
if(fl[u]) return;
fl[u]=1; b[u][u]=1;
for(int e=he[u];e;e=nxt[e]) {
int v=to[e];
dfs(v);
b[u]|=b[v];
}
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
int u,v; scanf("%d%d",&u,&v);
add(u,v);
}
for(int i=1;i<=n;i++) {
if(!fl[i]) {
dfs(i);
}
printf("%d\n",(int)b[i].count());
}
return 0;
}

浙公网安备 33010602011771号