给定一张 N 个点 M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。 输入格式 第一行两个整数 N,M,接下来 M 行每行两个整数 x,y,表示从 x 到 y 的一条有向边。 输出格式 输出共 N 行,表示每个点能够到达的点的数量。 数据范围 1≤N,M≤30000 输入样例: 10 10 3 8 2 3 2 5 5 9 5 9 2 3 3 9 4 8 2 10 4 9 输出样例: 1 6 3 3 2 1 1 1 1 1
#include <bitset>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int N = 30010;
int n, m;
int d[N];
bitset<N> f[N];//f[i][i] = 1表示 i 这个点在二进制数中也在第 i 位
int q[N], hh, tt = -1;
int h[N], e[N], ne[N], idx;
void add(int a, int b)//邻接表模板
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx;
idx ++ ;
}
void topsort()//拓扑排序模板
{
for (int i = 1; i <= n; i ++ )
if (!d[i]) q[++ tt] = i;
while (hh <= tt)
{
int t = q[hh ++ ];
for (int i = h[t]; i != -1; i = ne[i])
{
int j = e[i];
if (-- d[j] == 0) q[++ tt] = j;
}
}
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
while (m -- )
{
int a, b;
scanf("%d %d", &a, &b);
add(a, b);
d[b] ++ ;
}
topsort();
for (int i = n - 1; i >= 0; i -- )//从后往前遍历所有点
{
int j = q[i];
f[j][j] = 1;//点j肯定走到自己,将第j位的二进制数置为1.
for (int k = h[j]; k != -1; k = ne[k])
f[j] |= f[e[k]];//计算点j能到达的所有位置
}
for (int i = 1; i <= n; i ++ ) printf("%d\n", f[i].count());//该函数表示i这个点中二进制中1的数量
return 0;
}