题意:
如题所示
思路:
是个DAG可以想到用拓扑序,但是如何用拓扑序去快速得到答案呢?
用拓扑序地倒序去更新,比如有对于一个顶点u,它有这些出边u -> v1,u - > v2,u -> vk, vi 的拓扑序一定比u要大,我们先更新vi的可达到的点的有哪些再去更新u的,而u可以达到的点有哪些应该是u和所有vi能达到的点的并集,并集这里用bitset去做
#include <cstdio>
#include <algorithm>
#include <bitset>
#include <cstring>
#include <queue>
using namespace std;
const int N = 3e4+10;
bitset<N> f[N];
struct Node{
int to,nex;
}e[N];
int n,m,head[N],idx,in[N],order[N];
void add_edge(int u,int v){
e[idx].to = v;
e[idx].nex = head[u];
head[u] = idx++;
in[v]++;
}
void topo(){
queue<int> q;
int k = 0;
for(int i = 1;i <= n;i++){
if(!in[i]) q.push(i);
}
while(!q.empty()){
int u = q.front();q.pop();
order[k++] = u;
for(int i = head[u];~i;i = e[i].nex){
int v = e[i].to;
in[v]--;
if(!in[v]) q.push(v);
}
}
}
int main(){
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));idx = 0;
for(int i = 0;i < m;i++){
int u,v;scanf("%d%d",&u,&v);
add_edge(u,v);
}
topo();
for(int i = n-1;i >= 0;i--){
int u = order[i];
f[u][u] = 1;
for(int j = head[u];~j;j = e[j].nex){
f[u] |= f[e[j].to];
}
}
for(int i = 1;i <= n;i++){
printf("%d\n",f[i].count());
}
}