题意:给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.\((N,M<=30000)\)
分析:设\(f(x)\)表示x能够到达的点的集合,先求出该图的拓扑序,因为对于任意一条有向边(x,y),先要求出\(f(y)\)才能求出\(f(x)\).我们用\(bitset\)开f数组,把f[i]看作一个N位的二进制数,某一位为1则代表可以到达,对i的所有儿子做“按位或”运算即可把i的儿子能够到达的点统计到i上.
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<bitset>
using namespace std;
inline int read(){
int x=0,o=1;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')o=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*o;
}
const int N=30005;
int cnt,a[N];
int tot,head[N],nxt[N],to[N],deg[N];
bitset<N> f[N];
vector<int> Q[N];
queue<int>q;
inline void add(int a,int b){
nxt[++tot]=head[a];head[a]=tot;to[tot]=b;
++deg[b];
}
inline void topsort(int n){
for(int i=1;i<=n;++i)if(!deg[i])q.push(i);
while(q.size()){
int u=q.front();q.pop();
a[++cnt]=u;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];f[u][v]=1;
--deg[v];if(!deg[v])q.push(v);
}
}
}
int main(){
int n=read(),m=read();
for(int i=1;i<=m;++i){
int x=read(),y=read();
add(x,y);Q[x].push_back(y);
}
topsort(n);
for(int i=cnt;i>=1;--i){
for(int j=0;j<Q[a[i]].size();++j){
f[a[i]]|=f[Q[a[i]][j]];
}
}
for(int i=1;i<=n;++i)printf("%d\n",f[i].count()+1);
return 0;
}