【二进制$bitset$计数 异或求并集】 可达性统计
传送门
题意
给定\(n\)个点\(m\)条边的有向无环图,统计从每个点出发所能到达的点的数量
数据范围
\(1 \leq N, M \leq 30000\)
题解
统计的是从\(x\)出发的后继能够到达的点的并集和其自身。
用一个二进制数表示当前节点可以到的节点,第 \(i\) 位为\(1\)就是可以到达
\(f[i]\)就表示 \(i\) 可达的点,计算出来一个拓扑序列,
按照拓扑序列的倒序算过来即可,开始的时候所有点只能到达自己,从拓扑序列的从后一个点开始算递推即可,最后一个数没有出边。
\(bitset\)开数组
Code
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
const int N=3e4+10;
struct node
{
int to,ne;
}e[N];
int h[N],idx,deg[N],cnt;
int tops[N];
void add(int a,int b)
{
e[++idx].to=b;
e[idx].ne=h[a];
h[a]=idx;
deg[b]++;
}
int ans[N],n,m;
bitset<N>f[N];
void topsort()
{
queue<int>q;
rep(i,1,n+1) if(deg[i]==0) q.push(i);
while(q.size())
{
int t=q.front();
q.pop();
tops[++cnt]=t;
for(int i=h[t];i;i=e[i].ne)
{
int to=e[i].to;
if(--deg[to] == 0) q.push(to);
}
}
}
void cal()
{
per(i,1,cnt+1)
{
int t=tops[i];
f[t][t]=1;
for(int i=h[t];i;i=e[i].ne) f[t]|=f[e[i].to];
}
}
int main()
{
cin>>n>>m;
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);
}
topsort();
cal();
rep(i,1,n+1) cout<<f[i].count()<<endl;
}

浙公网安备 33010602011771号