AcWing 164. 可达性统计
给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量。
输入格式
第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边。
输出格式
输出共N行,表示每个点能够到达的点的数量。
数据范围
1≤N,M≤30000
显然可以用拓扑排序+状态压缩来做, 用一个n位的二进制数存每一个f[x], 其中第i位是1表示x能到i,0则不能到i, 这样就相当于存在x 到 y的一条边,f[x] |= f[y], 再预处理处拓扑序, 反向枚举, 最后判断每个f[i]中的个数, 但有一个bug就是, 就算unsigned long long 二进制下只有64位, 这里就有一个小小的干货:
关于状态压缩 bitset容器:
转载:https://oi-wiki.org/ds/stl/bitset/
介绍¶
std :: bitset 是标准库中的一个固定大小序列,其储存的数据只包含 0/1
众所周知,由于内存地址是按字节即 byte 寻址,而非比特 bit ,
我们一个 bool 类型的变量,虽然只能表示 0/1 , 但是也占了 1byte 的内存
bitset 就是通过固定的优化,使得一个字节的八个比特能分别储存 8 位的 0/1
对于一个 4 字节的 int 变量,在只存 0/1 的意义下, bitset 占用空间只是其
在某些情况下通过 bitset 可以使你的复杂度除以 32
当然, vector 的一个特化 vector<bool> 的储存方式同 bitset 一样,区别在于其支持动态开空间,
bitset 则和我们一般的静态数组一样,是在编译时就开好了的。
那么为什么要用 bitset 而非 vector<bool> ?
通过以下的介绍,你可以更加详细的看到 bitset 具备的方便操作
#include <bitset> // 包含 bitset 的头文件
运算符¶
operator[] : 访问其特定的一位
operator ==/!= : 比较两个 bitset 内容是否完全一样
operator &=/|=/^=/~ : 进行按位与/或/异或/取反操作
operator <</>>/<<=/>>= : 进行二进制左移/右移
operator <</>> : 流运算符,这意味着你可以通过 cin/cout 进行输入输出
vector<bool> 只具有前两项
成员函数¶
test() : 它和 vector 中的 at() 的作用是一样的,和 [] 运算符的区别就是越界检查
count() : 返回 true 的数量
set() : 将整个 bitset 设置成 true , 你也可以传入参数使其设置成你的参数
reset() : 将整个 bitset 设置成 false
flip() : 翻转该位 (0 变 1,1 变 0), 相当于逻辑非/异或 1
to_string() : 返回转换成的字符串表达
to_ulong() : 返回转换成的 unsigned long 表达 ( long 在 NT 及 32 位 POSIX 系统下与 int 一样,在 64 位 POSIX 下与 long long 一样)
to_ullong() C++11, 返回转换成的 unsigned long long 表达
这些 vector<bool> 基本都没有
作用¶
一般来讲,我们可以用 bitset 优化一些可行性 DP, 或者线筛素数 ( notprime 这种 bool 数组可以用 bitset 开到 之类的)
它最主要的作用还是压掉了内存带来的时间优化, 的常数优化已经可以是复杂度级别的优化了,比如一个 的 算法, 显然很卡,在常数大一点的情况下必然卡不过去,O(松)不能算!, 这时候如果我们某一维除以 32, 则可以比较保险的过了这道题
其实 bitset 不光是一个容器,更是一种思想,我们可以通过手写的方式,来把 long long 什么的压成每 bit 表示一个信息,用 STL 的原因更多是因为它的运算符方便
作者:Chicago
链接:https://www.acwing.com/solution/acwing/content/899/
来源:AcWing
#include <bits/stdc++.h>using namespace std;typedef long long ll; const int INF = 0x3f3f3f3f; const int MAXN = 3e4 + 100; const int MAXM = 3e3 + 10; const double eps = 1e-5;template < typename T > inline void read(T &x) {x = 0; T ff = 1, ch = getchar();while(!isdigit(ch)) {if(ch == '-') ff = -1;ch = getchar();}while(isdigit(ch)) {x = (x << 1) + (x << 3) + (ch ^ 48);ch = getchar(); }x *= ff; }template < typename T > inline void write(T x) {if(x < 0) putchar('-'), x = -x;if(x > 9) write(x / 10);putchar(x % 10 + '0'); }int n, m, top, in[MAXN], b[MAXN]; bitset < MAXN > a[MAXN]; int lin[MAXN], tot = 0; struct edge {int y, next; }e[MAXN];inline void add(int xx, int yy) {e[++tot].y = yy;e[tot].next = lin[xx];lin[xx] = tot; }void topsort() {queue < int > q;for(int i = 1; i <= n; ++i) {if(in[i] == 0) q.push(i);} while(!q.empty()) {int x = q.front(); q.pop();b[++top] = x;for(int i = lin[x], y; i; i = e[i].next) {if(--in[y = e[i].y] == 0) q.push(y); } }}int main() {read(n); read(m);for(int i = 1; i <= m; ++i) {int x, y;read(x); read(y);add(x, y);in[y]++;} topsort();for(int i = top; i >= 1; --i) {int x = b[i];a[x][x] = 1;for(int j = lin[x]; j; j = e[j].next) {a[x] |= a[e[j].y]; }} for(int i = 1; i <= n; ++i) {cout << a[i].count() << endl;}return 0; }
转载于:https://www.cnblogs.com/AK-ls/p/11106434.html
AcWing 164. 可达性统计相关推荐
- Acwing 164.可达性统计(Java)
题目描述: 给定一张 N 个点 M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数 N,M,接下来 M 行每行两个整数 x,y,表示从 x 到 y 的一条有向边. ...
- 164. 可达性统计【拓扑排序 / bitset】
无环说明一定有拓扑排序. 我们得到拓扑排序,倒着推.注意压位. #include<bits/stdc++.h> #include<bitset> using namespace ...
- AcWing P164 可达性统计 题解
Analysis 这道题我一开始想到的是传递闭包,但是时间复杂度是n³,也开不下30000*30000的数组,所以我想到了拓扑+状态压缩(bitset),从后往前找,把能到达的点能到哪里用位运算赋到上 ...
- P6134 [JSOI2015]最小表示(拓扑排序递推 + bitset优化,可达性统计变种)
整理的算法模板合集: ACM模板 P6134 [JSOI2015] 题目要求删除一条边整个图的连通性是不受影响的,也就是说如果我们要删除边(x,y)(x,y)(x,y),删除以后整个图的连通性不受影响 ...
- [2021-09-02 contest]CF1251C,可达性统计(bitset优化dp),Boomerang Tournament(状压dp),小蓝的好友(mrx)(treap平衡树)
文章目录 CF1251C Minimize The Integer acwing164:可达性统计 Facebook Hacker Cup 2016 Round 1 Boomerang Tournam ...
- 「CH2101」可达性统计 解题报告
CH2101 可达性统计 描述 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到 ...
- 【AcWing】数位统计DP、树形DP、状态压缩DP、记忆化搜索
[AcWing]数位统计DP.树形DP.状态压缩DP.记忆化搜索 一.数位统计DP 二.状态压缩DP 三.树形DP 四.记忆化搜索 一.数位统计DP 计数问题 给定两个整数 a 和 b,求 a 和 b ...
- 可达性统计(拓扑排序)
描述 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 ...
- 可达性统计(拓扑排序逆推)
给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 输出共N行,表示每个点能 ...
最新文章
- 深度解读 OpenYurt :边缘自治能力设计解析
- Webstorm+cordova打包vue成Android项目
- 一张图看懂android事件分发原理
- 记一次在LAMP中遇到的问题
- list对oracle结果集排序了_详解SQL窗口函数和分组排序函数
- JAVA基础实例(三)--排序
- ModBus协议寄存器
- Spring data JPA方法命名规则
- ASP.NET vNext 概述
- 如何在EJB3中JNDI调用SessionBean(二)
- 【疾病分类】基于matlab LBP果实病害检测分类【含Matlab源码 1714期】
- php 打印机样式自动对齐,虚拟打印机怎么快速设置视图样式
- 视频编码中CBR编码和VBR编码的区别
- Python每输出n个换行
- 开发者 发展 程序物语
- 高温熔融玻璃液位检测用激光玻璃液位计
- Rust websocket 客户端实现
- robots.txt介绍
- 2021年软考考试科目怎么安排?
- 点餐小程序系统/基于微信小程序的点餐系统/点餐平台网站
热门文章
- Android PC投屏简单尝试—最终章1
- 手动命令行编译APK
- 【译】A Hitchhiker’s Guide to Consensus Algorithms
- 关于android设备管理器的一些分析
- ARM64的启动过程之(五):UEFI
- java channelexec_java-使用SSH exec通道调用Shell脚本,但忽略对其他Shell脚本的调用
- arcgis 字段计算器 条件赋值_【教程】ArcGIS入门教程(11)——多条件购房分析...
- Qt 关于定时器实用的总结
- Elastic Nodes Example 翻译及学习整理
- poj2449(第k短路)