给定一张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. 可达性统计相关推荐

  1. Acwing 164.可达性统计(Java)

    题目描述: 给定一张 N 个点 M 条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数 N,M,接下来 M 行每行两个整数 x,y,表示从 x 到 y 的一条有向边. ...

  2. 164. 可达性统计【拓扑排序 / bitset】

    无环说明一定有拓扑排序. 我们得到拓扑排序,倒着推.注意压位. #include<bits/stdc++.h> #include<bitset> using namespace ...

  3. AcWing P164 可达性统计 题解

    Analysis 这道题我一开始想到的是传递闭包,但是时间复杂度是n³,也开不下30000*30000的数组,所以我想到了拓扑+状态压缩(bitset),从后往前找,把能到达的点能到哪里用位运算赋到上 ...

  4. P6134 [JSOI2015]最小表示(拓扑排序递推 + bitset优化,可达性统计变种)

    整理的算法模板合集: ACM模板 P6134 [JSOI2015] 题目要求删除一条边整个图的连通性是不受影响的,也就是说如果我们要删除边(x,y)(x,y)(x,y),删除以后整个图的连通性不受影响 ...

  5. [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 ...

  6. 「CH2101」可达性统计 解题报告

    CH2101 可达性统计 描述 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到 ...

  7. 【AcWing】数位统计DP、树形DP、状态压缩DP、记忆化搜索

    [AcWing]数位统计DP.树形DP.状态压缩DP.记忆化搜索 一.数位统计DP 二.状态压缩DP 三.树形DP 四.记忆化搜索 一.数位统计DP 计数问题 给定两个整数 a 和 b,求 a 和 b ...

  8. 可达性统计(拓扑排序)

    描述 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 ...

  9. 可达性统计(拓扑排序逆推)

    给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 输出共N行,表示每个点能 ...

最新文章

  1. 深度解读 OpenYurt :边缘自治能力设计解析
  2. Webstorm+cordova打包vue成Android项目
  3. 一张图看懂android事件分发原理
  4. 记一次在LAMP中遇到的问题
  5. list对oracle结果集排序了_详解SQL窗口函数和分组排序函数
  6. JAVA基础实例(三)--排序
  7. ModBus协议寄存器
  8. Spring data JPA方法命名规则
  9. ASP.NET vNext 概述
  10. 如何在EJB3中JNDI调用SessionBean(二)
  11. 【疾病分类】基于matlab LBP果实病害检测分类【含Matlab源码 1714期】
  12. php 打印机样式自动对齐,虚拟打印机怎么快速设置视图样式
  13. 视频编码中CBR编码和VBR编码的区别
  14. Python每输出n个换行
  15. 开发者 发展 程序物语
  16. 高温熔融玻璃液位检测用激光玻璃液位计
  17. Rust websocket 客户端实现
  18. robots.txt介绍
  19. 2021年软考考试科目怎么安排?
  20. 点餐小程序系统/基于微信小程序的点餐系统/点餐平台网站

热门文章

  1. Android PC投屏简单尝试—最终章1
  2. 手动命令行编译APK
  3. 【译】A Hitchhiker’s Guide to Consensus Algorithms
  4. 关于android设备管理器的一些分析
  5. ARM64的启动过程之(五):UEFI
  6. java channelexec_java-使用SSH exec通道调用Shell脚本,但忽略对其他Shell脚本的调用
  7. arcgis 字段计算器 条件赋值_【教程】ArcGIS入门教程(11)——多条件购房分析...
  8. Qt 关于定时器实用的总结
  9. Elastic Nodes Example 翻译及学习整理
  10. poj2449(第k短路)