C++ STL模板库 bitset

bitset

  • 简介

       bitset可看作一一个多位二进制数,每8位占用1个字节,相当于采用了状态压缩的二进制数组,并支持基本的位运算。在估算程序运行的时间时,我们一般以32位整数的运算次数为基准,因此n位bitset执行一次位运算的复杂度可视为 n/32, 效率较高。

  • 用法

bitset<100> a
表示100位二进制数, <>中填需要的位数。

  • 位运算

取反:~a: 返回对bitsets按位取反的结果。

与或非:&, |, ^: 返回对两个位数相同的bitset执行按位与、或、异或运算的结果。

左移 右移: >>, <<: 返回把一个 bitset右移、左移若干位的结果。

大小比较: ==, !=: 比较两个bitset代表的二进制数是否相等。

  • 函数

count: a.count() , 返回有多少位为1。

any/none: 若a所有位都为0,则a.any() 返回false, a.none()返回 true。若a至少一位为1, 则a.anyO返回true, a.none()返回false.

set:
a.set() 把a所有位变为1.
a.set(k, v) 把a 的第k为变为v, a[k] = v.

rset:
a.rset() 把a所有位变为0.
a.rset(k) 把a 的第k为变为0, a[k] = 0.

flip:
a.flip() 把a所有位取反.
a.flip(k) 把a 的第k位取反, a[k] ^= 1.

题目大意
给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量。数据范围 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

思路

       从x出发能够到达的点,是从x的各个后继节点y出发能够到达的点的并集,再加上点x自身。所以,在计算出一个点的所有后继节点的f值之后,就可以计算出该点的f值。这启发我们先用拓扑排序算法求出一个拓扑序,然后按照拓扑序的倒序进行计算一因为在拓扑序中, 对任意的一条边(x,y), x都排在y之前。

       我们可以使用一个N位二进制数存储每个f(x),其中第i位是1表示x能到i, 0表示不能到i。这样-来,对若干个集合求并,就相当于对若干个N位二进制数做“按位或”运算。最后,每个f(x)中1的个数就是从x出发能够到达的节点数量。

       这个N位二进制数可以压缩成N/32+1个无符号32位整数unsigned int进行存储,直接使用C++ STL中为我们提供的bitset

代码

#include<iostream>
#include<algorithm>
#include<string.h>
#include<bitset>
#include<queue>
using namespace std;
const int N = 30010;
int n, m;
int head[N], e[N], ne[N], idx;
int d[N], seq[N];
bitset<N> f[N];
void add(int a, int b){
	e[idx] = b;
	ne[idx] = head[a];
	head[a] = idx++; 
}
void topsort(){
	queue<int> q;
	for(int i = 1; i <= n; i++){
		if(!d[i])
		q.push(i);		
	}
	int k = 0;
	while(q.size()){
		int t = q.front();
		q.pop();
		seq[k++] = t;
		for(int i = head[t]; ~i; i = ne[i]){
			int j = e[i];
			if(--d[j] == 0)
				q.push(j);
		}
	}
}
int main(){
	cin >> n >> m;
	memset(head, -1, sizeof head);
	for(int i = 0; i < m; i++){
		int a, b;
		cin >> a >> b;
		add(a, b);
		d[b]++;
	}
	topsort();
	for(int i = n - 1; ~i; i--){
		int j = seq[i];
		
		f[j][j] = 1;
		for(int p = head[j]; ~p; p = ne[p]){
			f[j] |= f[e[p]];
		} 
	}	
	for(int i = 1; i <= n; i++){
		cout << f[i].count() << endl;
	}
	return 0;
}

发布了54 篇原创文章 · 获赞 155 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_45432665/article/details/104083022