其他分享
首页 > 其他分享> > [Acwing 164. 可达性统计] 题解报告

[Acwing 164. 可达性统计] 题解报告

作者:互联网

事实上,这道题并不需要拓扑排序。(当然,拓扑排序还是更快)

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 30010;
    
    int f[N];
    int n, m;
    int h[N], e[N], ne[N], idx;
    
    void add(int a, int b)
    {
        e[ ++ idx] = b, ne[idx] = h[a], h[a] = idx;
    }
    
    void dfs(int u)
    {
        if (f[u]) return;
        int s = 1;
        
        for (int i = h[u]; i; i = ne[i])
        {
            int j = e[i];
            dfs(j);
            s += f[j];
        }
        
        f[u] += s;
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
            
        for (int i = 1, x, y; i <= m; i ++ )
            scanf("%d%d", &x, &y), add(x, y);
        
        for (int i = 1; i <= n; i ++ )
            if (!f[i])
                dfs(i);
        
        for (int i = 1; i <= n; i ++ )
            printf("%d\n", f[i]);
            
        return 0;
    }

然鹅,我们没有考虑到一种情况,如图:
graph.png

如果按照刚才上面的做法,那么 \(5, 6\) 号节点就会被统计两次,造成结果偏大。

所以,我们需要记录一下每个出点可到点的并集,这可以用 \(bitset\) 来实现

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <bitset>

using namespace std;

const int N = 30010;
int n, m; 
int h[N], e[N], ne[N], idx;
bitset<N> f[N];

void add(int a, int b)
{
	e[ ++ idx] = b, ne[idx] = h[a], h[a] = idx;
}

void dfs(int u)
{
	if (f[u].any()) return;
	
	f[u][u] = 1;
	bitset<N> s;
	
	for (int i = h[u]; i; i = ne[i])
	{
		int j = e[i];
		dfs(j);
		s |= f[j];
	}
	
	f[u] |= s;
}

int main()
{
	scanf("%d%d", &n, &m);
	
	while (m -- )
	{
		int a, b;
		scanf("%d%d", &a, &b);
		add(a, b);
	}
	
	for (int i = 1; i <= n; i ++ )
		if (f[i].none())
			dfs(i);
			
	for (int i = 1; i <= n; i ++ )
		printf("%d\n", f[i].count());
		
	return 0;
}

标签:idx,int,题解,void,ne,bitset,164,include,可达性
来源: https://www.cnblogs.com/LcyRegister/p/16185368.html