2101 可达性统计
2101 可达性统计
描述
给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量。N,M≤30000。
输入格式
第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边。
输出格式
共N行,表示每个点能够到达的点的数量。
- 用f(x)表示从x出发能到达的点的集合,则它相当于从x的各个后继出发能到的点得并集再加上x本身,所以说在计算出x的所有后继节点的f值后就能得到x的f值。所以用到拓扑排序
- 我们先求出一个拓扑序,然后按拓扑序倒着计算——因为拓扑序中保证了对于任意的(x,y),x都排在y之前。
- 利用bitset表示每个点能到达的点
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cstring> 5 #include <queue> 6 #include <bitset> 7 using namespace std; 8 9 #define res register int 10 const int N=30000+10; 11 int head[N],ver[N<<1],nxt[N<<1],deg[N],n,m,tot(0); 12 int a[N],cnt(0); 13 bitset<N> f[N]; 14 15 inline void add(int x,int y) { 16 ver[++tot]=y; nxt[tot]=head[x]; head[x]=tot; 17 } 18 19 queue<int> q; 20 inline void toposort() 21 { 22 for(res i=1 ; i<=n ; i++) if(!deg[i]) q.push(i); 23 while(q.size()) 24 { 25 int x=q.front(); q.pop(); a[++cnt]=x; 26 for(res i=head[x] ; i ; i=nxt[i]) 27 { 28 int y=ver[i]; 29 if((--deg[y])==0) q.push(y); 30 } 31 32 } 33 } 34 35 int main() 36 { 37 scanf("%d %d",&n,&m); 38 for(res i=1 ; i<=m ; i++) 39 { 40 int x,y; scanf("%d %d",&x,&y); 41 add(x,y); deg[y]++; 42 } 43 toposort(); 44 for(res i=cnt ; i>=1 ; i--) 45 { 46 int x=a[i]; 47 f[x][x]=1; 48 for(res j=head[x] ; j ; j=nxt[j]) 49 { 50 int y=ver[j]; 51 f[x]|=f[y]; 52 } 53 } 54 for(res i=1 ; i<=n ; i++) printf("%d\n",f[i].count()); 55 return 0; 56 }