可达性统计

颓了好久终于写了个题了

题目链接

点这里,咕咕咕

思路

给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量。

设从\(x\)点出发能到达的点构成的集合\(f(x)\)

\[f(x)={x} \cup\Bigg(\bigcup \ \ \ f(y)\Bigg)(x,y联通) \]

发现从\(x\)出发能到的点,是从\(x\)的各个后继节点\(y\)出发能到的点的并集(用状态压缩来表示状态),所以我们可以拓扑排序求出拓扑序,然后倒序计算

代码

#include<bits/stdc++.h>
#include<bitset>
using namespace std;
const int N=30011;
queue<int>q;
bitset<N>f[N];
int du[N],n,m,cnt,head[N],tp[N],len;
struct node {
	int u,v,Next;
} e[N];
void add(int u,int v) {
	e[++cnt].u=u;
	e[cnt].v=v;
	e[cnt].Next=head[u];
	head[u]=cnt;
}
void topsort() {
	for(int i=1; i<=n; ++i) if(du[i]==0) q.push(i);
	while(!q.empty()) {
		int to=q.front();
		q.pop();
		tp[++len]=to;
		for(int i=head[to]; i; i=e[i].Next) {
			int To=e[i].v;
			if((--du[To])==0) q.push(To);
		}

	}
}
int  main() {
	cin>>n>>m;
	for(int i=1; i<=m; ++i) {
		int x,y;
		cin>>x>>y;
		add(x,y);
		du[y]++;
	}
	topsort();
	for(int i=len; i>=1 ; --i) {
		int u=tp[i];
		f[u][u]=1;
		for(int j=head[u]; j; j=e[j].Next) {
			int v=e[j].v;
			f[u] |= f[v];
		}
	}
	for(int i=1; i<=n; ++i) {
		cout<<f[i].count()<<'\n';
	}
	return 0;
}

错误原因

1.bitset开小了
2.f[u] |= f[v];写成了f[i]|=f[v];我真是太二了
posted @ 2019-08-14 17:36  pyyyyyy  阅读(310)  评论(0编辑  收藏  举报