• Acwing 164. 可达性统计(拓扑排序+bitset)


    地址:https://www.acwing.com/problem/content/166/

     

    题意:

    求每个点所能到达的点数目,包含自身。

    解析:

    一:已知为有向无环图,那么可以考虑用拓扑排序。

    假设有图:

    1->2->3->4

    5->3

    拓扑排序结果:

    1->2-5->3->4

    那么求每个点所能到达的点,是需要从右往左看的。对于5,它能到达5,3,4。对于2,它能到达2,5,3,4。那么求1所能到达的点,直接累加f[2]和f[5]是不行的,有重复点。所以我们需要求两者并集:f[2]Uf[5]=={2,5,3,4}

    如果我们把n个点,看为一个长度为n+1(0不算点)的二进制,f[i][1]==1表示,i点能到1号点,==0则表示不能到。

    那么对于一个点,先把它本身f[i][i]标为1,然后遍历它的出边,与它们两两进行 | 运算即可。

    二:关于bitset

    #include<bitset>

    bitset<maxn>f[maxn]

    f[].set()表示全变为1,括号内填入 i 表明将第i+1位变1

    f[].reset()表示全变为0,括号内填入 i 表明将第i+1位变0

    f[].flip()全取反

    f[].count()求二进制所含1的数目

    为了更直观地说明其在本题的作用,给出测试代码和运行截图:

    bitset<5>f[maxn];
    int main()
    {
        f[1][2]=1;//1->2
        f[1][3]=1;//1->3
        f[3][2]=1;//3->2
        cout<<f[1]<<endl;
        cout<<f[3]<<endl;
        f[3]|=f[1];//取并集
        cout<<f[3]<<endl;
        cout<<f[3].count();//求所含1的数目
    }

    三:AC代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<bitset>
    #include<queue>
    using namespace std;
    const int maxn=3e4+10;
    int ans[maxn],tot=0;
    int e[maxn],ne[maxn],idx,h[maxn],d[maxn];
    int n,m;
    bitset<maxn>f[maxn];
    void init()
    {
        memset(h,-1,sizeof(h));
        idx=0;
    }
    void add(int a,int b)
    {
        e[idx]=b;
        ne[idx]=h[a];
        h[a]=idx++;
    }
    void bfs()
    {
        queue<int>q;
        for(int i=1;i<=n;i++)
            if(d[i]==0)
                q.push(i);
        while(!q.empty())
        {
            int t=q.front();
            q.pop();
            ans[tot++]=t;
            for(int i=h[t];i!=-1;i=ne[i])
            {
                int j=e[i];
                d[j]--;
                if(d[j]==0)
                {
                    q.push(j);
                }
            }
        }
    }
    int main()
    {
        cin>>n>>m;
        init();
        for(int i=1;i<=m;i++)
        {
            int a,b;
            cin>>a>>b;
            add(a,b);
            d[b]++;
        }
        bfs();
        for(int i=tot-1;i>=0;i--)
        {
            int now=ans[i];
            f[now][now]=1;
            for(int j=h[now];j!=-1;j=ne[j])
            {
                f[now]|=f[e[j]];
            }
        }
        for(int i=1;i<=n;i++)
            cout<<f[i].count()<<endl;
    }
  • 相关阅读:
    系统集成项目管理工程师高频考点(第一章)
    2、无重复字符的最长子串
    1、爬楼梯
    webpack起步
    Centos7安装nginx
    Centos7安装nacos
    Centos7安装java和maven
    centos7安装fastDFS
    aop中获取请求消息和属性
    数据库面对高并发的思路
  • 原文地址:https://www.cnblogs.com/liyexin/p/13996024.html
Copyright © 2020-2023  润新知