题目:可达性统计
题意:给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量。
思路:建图之后采用拓扑排序,然后反向遍历,使用bitset去标记所有可以走的点
代码:
#include<iostream>
#include<bitset>
#include<queue>
#include<string.h>
using namespace std;
const int maxn = 30010;
int n, m;
int h[maxn], e[maxn], ne[maxn], id, degree[maxn], rk[maxn];
bitset<maxn>vis[maxn];
int cn = 0;
void add(int u, int v) //前向星建图
{
e[id] = v;
ne[id] = h[u];
h[u] = id++;
}
void TopSort() //拓扑排序
{
queue<int> q;
for(int i = 1; i <= n; i++)
{
if(degree[i] == 0)q.push(i);
}
while(!q.empty())
{
int t = q.front();
q.pop();
rk[cn++] = t;//保存拓扑排序的结果
for(int i = h[t]; ~i; i = ne[i])
{
int k = e[i];
degree[k]--;
if(degree[k] == 0)q.push(k);
}
}
}
int main()
{
cin>>n>>m;
int id = 0;
memset(h, -1, sizeof(h));//初始化h
for(int i = 1; i <= m; i++)
{
int u, v;
cin>>u>>v;
add(u, v);
degree[v]++;
}
TopSort();
for(int i = n-1; ~i; i --)
{
int j = rk[i];
vis[j][j] = 1;
for(int k = h[j]; ~k; k = ne[k])
vis[j] |= vis[e[k]];
}
for(int i = 1; i <= n; i++)cout<<vis[i].count()<<endl;
return 0;
}