就是给你一个n个点m条边的有向无环图,要你求每个点可以到达多少个点(含本身)
这题一开始我是想bfs还是dfs的,数据范围是30000,显然不能dfs,bfs做了错了QAQ
后来发现可以用拓扑排序,因为拓扑序是只能从x到y,所以总的每个点的数量就是本身+那个点可以到达的点的数量总和
数据范围30000,考虑二进制状态压缩,|起来
有一个小细节,在处理拓扑序的时候,是要倒序,因为拓扑序只能从x指向y,要求所有连边点个数的总和,那点的数量需要提前就要知道了,需要倒序,每个拓扑点都处理一遍(就,有点类似于递推吧)
板子要熟悉:拓扑排序的板子
#include<iostream>
#include<cstring>
#include<queue>
#include<bitset>
using namespace std;
int n,m,k;
const int N=30010;
int h[N],e[N],ne[N],idx,din[N],seq[N];//din是入度,seq是拓扑序
bitset<N> f[N];
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(!din[i])
q.push(i);
while(q.size())
{
auto t=q.front();
q.pop();
seq[k]=t;
k++;
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
din[j]--;
if(!din[j]) q.push(j);
}
}
}
int main(){
memset(h,-1,sizeof(h));
cin>>n>>m;
while(m--)
{
int a,b;
cin>>a>>b;
add(a,b);
din[b]++;
}
topsort();
for(int i=n-1;i>=0;i--)
{
int j=seq[i];
f[j][j]=1;//本身是1
for(int u=h[j];u!=-1;u=ne[u])
{
f[j]|=f[e[u]];
}
}
for(int i=1;i<=n;i++) cout<<f[i].count()<<endl;
return 0;
}