1. 程式人生 > 實用技巧 >閉包傳遞

閉包傳遞

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;
}