拓扑排序用bitset处理相同排名的集合

前言

拓扑排序可以在有向无环图中以偏序求出全序,但是在一些图中,有些结点的rank是一样高的,(除非题目有特殊说明,编号小的rank高等情况),这样是不能求出正确的rank的。这时候,我们可以加入bitset,用bitset处理相同rank的结点集。

bitset

使用头文件 bitset

bitset类似于一个bool类型的数组,存放着01。可以在定义的时候进行初始化操作,可以用下标进行访问,也是从0开始,并且从默认最右边的一位为[0](结合二进制数,其实很人性化),定义、访问及初始化方法如下:

int main()
{
    bitset<10> q(3);
    cout << q << endl;
    for (int i = 0; i < 10; i++)
        cout << q[i] << ' ';
    cout << endl;
    bitset<10> b("1110");
    cout << q << endl;
    /*
Output:
0000000011                                        
1 1 0 0 0 0 0 0 0 0
0000000011
*/
    return 0;
}

bitset的一些内置方法:
s.set():把s所有位初始化为1
s.reset():把s所有位初始化为0
s.set(k):把s的第k位设置为1
s.reset(k):把s的第k位设置为0
s.count():返回1的个数
s.any():返回是否有1
s.none():返回是否没有1

另外bitset支持位运算,这也是它很重要的一个优点。

拓扑排序使用bitset

先上一个例题:核弹剑仙

这题其实就是让你求每个结点的rank,并且可能有并列的情况,这时候我们就可以用bitset和拓扑来进行转移,bitset[i][j]表示结点j是否比i的rank高。
建图的时候u到v的单向路径表示u的rank高于v的rank,这样我们拓扑排序+bitset进行转移即可。

最后配合s.count()进行输出

AC代码:

ll head[1010];
ll ct = 1;
struct node
{
    ll v, next;
} e[2010];
void add(ll u, ll v)
{
    e[ct].v = v;
    e[ct].next = head[u];
    head[u] = ct++;
}

ll degree[1010];
ll n, m;
queue<int> q;
bitset<1010> sum[1010];
void topo()
{
    ll pos;
    for (int j = 1; j <= n; j++)
        if (!degree[j])
            q.push(j);
    while (q.size())
    {
        pos = q.front();
        q.pop();
        degree[pos] = INF;
        for (int i = head[pos]; i; i = e[i].next)
        {
            sum[e[i].v][pos] = 1;    //u比v的rank高
            sum[e[i].v] |= sum[pos]; //使用位运算
            degree[e[i].v]--;
            if (degree[e[i].v] == 0)
                q.push(e[i].v);
        }
    }
}
int main()
{
    scanf("%lld%lld", &n, &m);
    for (int i = 1; i <= m; i++)
    {
        ll a, b;
        scanf("%lld%lld", &a, &b);
        degree[b]++;
        add(a, b);
    }
    topo();
    for (int i = 1; i <= n; i++)
        cout << sum[i].count() << endl;
    return 0;
}
参考资料
  1. C++ bitset——高端压位卡常题必备STL
  2. bitset【C++STL】
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hesorchen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值