1.题目给定有向无环图可以想到拓扑排序,设点x出发能够到达的点构成的集合是f(x),那么从点x出发能够到达的点,就是x自身和x的后继节点的并集,排序后逆序枚举,f第一维代表哪一个节点,第二维是01串,代表哪些点可达,或运算即可。
注:int型的1e6大约4M
#include<bits/stdc++.h>
using namespace std;
const int N=30010;
int n,m;
int h[N],e[N],ne[N],idx;
int d[N],seq[N];
bitset<N> f[N]; //用来统计f【i】中有多少个一(二维数组)
void add(int a,int b){
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void topsort(){
queue<int> q;
for(int i=1;i<=n;i++){
if(!d[i]) q.push(i);
}
int k=0;
while(!q.empty()){
int t=q.front();
q.pop();
seq[k++]=t;
for(int i=h[t];i!=-1;i=ne[i]){
int j=e[i];
if(--d[j]==0) q.push(j);
}
}
}
int main(){
cin>>n>>m;
memset(h,-1,sizeof(h));
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
add(a,b);
d[b]++;
}
topsort();
for(int i=n-1;i>=0;i--){
int j=seq[i];
f[j][j]=1; //可以到达自己
for(int k=h[j];k!=-1;k=ne[k]){
f[j]|=f[e[k]];
}
}
for(int i=1;i<=n;i++) cout<<f[i].count()<<endl;
return 0;
}