可达性统计
题意:
给定一张 N 个点 M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量。
1 ≤ N , M ≤ 30000 1≤N,M≤30000 1≤N,M≤30000
思路:
给定DAG图,多半是要topsort + dp。
可以通过建反图来得到当前点出发到达点的数量。
例如: u–> v, v能到达的点,那么u也能到达。u要对v能到达的点取并集。
假设不使用bitset,要二进制状压表示当前点能到达的点。当然数据范围用状压铁T,就算数据范围小点,状压不T,还要涉及到取
o
r
or
or操纵,需要O(n)。
假设使用bitset,那么题目变得非常简单,且每次
o
r
or
or操纵 O(n / 32)。
那么总的实际复杂度为O(n * n / 32)
code:
int h[maxn], ne[maxn], e[maxn], idx, in[maxn];
bitset <mx> f[mx];int N, M;
void add(int u, int v)
{
e[idx] = v;
ne[idx] = h[u];
h[u] = idx ++;
} //含重边 非连通图
void topsort()
{
queue <int> alls;
for(int i = 1 ; i <= N ; i ++)
{
if(in[i] == 0)
alls.push(i), f[i][i] = 1;
}
while(!alls.empty())
{
int temp = alls.front();
alls.pop();
for(int i = h[temp] ; i != -1 ; i = ne[i])
{
int son = e[i];
f[son][son] = 1;
f[son] |= f[temp];
in[son] --;
if(in[son] == 0)
alls.push(son);
}
}
}
int main() //建反边 bitset
{
scanf("%d %d", &N, &M);
memset(h, -1, sizeof(h)), idx = 0;
for(int i = 1 ; i <= M ; i ++)
{
int u, v;
scanf("%d %d", &u, &v);
// add(u, v);
add(v, u);
in[u] ++;
}
topsort();
for(int i = 1 ; i <= N ; i ++)
printf("%d\n", f[i].count());
return 0;
}