题目链接:https://www.acwing.com/problem/content/description/166/
计算有向无环图中每个点可达的点的数量,可以先通过拓扑排序确定点的拓扑序,因为在一个点处理之前,他所能到达的所有点都要先被处理,所以我们处理的顺序
只要是按照拓扑排序的逆序处理就能在这个点被处理之前就把该点所能到达的所有点都先处理完.这道题的空间复杂度经过计算可以发现约是1e7,128M空间
代码:
#include<iostream> #include<bitset> #include<queue> #include<string.h> #define maxn 30010 using namespace std; int head[maxn],nxt[maxn],ver[maxn]; bitset<30010> f[30010]; int a[maxn];//存放top序 int deg[maxn]; int tot=0; int n,m; int cnt=0; void addedge(int u,int v){ ver[++tot]=v; nxt[tot]=head[u]; head[u]=tot; } void topsort(){ queue<int> q; for(int i=1;i<=n;i++)if(!deg[i])q.push(i); while(!q.empty()){ int x=q.front(); q.pop(); a[++cnt]=x; for(int i=head[x];i;i=nxt[i]){ int y=ver[i]; if(!(--deg[y]))q.push(y); } } } void calc(){ for(int i=cnt;i>=1;i--){ int x=a[i];//按照topsort的逆序进行处理 f[x][x]=1;//设置顶点x能到达它自己 for(int i=head[x];i;i=nxt[i]){ int y=ver[i]; f[x]|=f[y]; } } } int main(){ cin>>n>>m; for(int i=0;i<m;i++){ int u,v; scanf("%d%d",&u,&v); addedge(u,v); deg[v]++; } topsort(); calc(); for(int i=1;i<=n;i++)printf("%d ",f[i].count()); }