闭包传递

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\)

bitsets;
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;
}
posted @ 2020-11-27 15:14  wwwsfff  阅读(93)  评论(0)    收藏  举报