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 + ;
const int MAXM = 3e3 + ;
const double eps = 1e-; template < typename T > inline void read(T &x) {
x = ; T ff = , ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') ff = -;
ch = getchar();
}
while(isdigit(ch)) {
x = (x << ) + (x << ) + (ch ^ );
ch = getchar();
}
x *= ff;
} template < typename T > inline void write(T x) {
if(x < ) putchar('-'), x = -x;
if(x > ) write(x / );
putchar(x % + '');
} int n, m, top, in[MAXN], b[MAXN];
bitset < MAXN > a[MAXN];
int lin[MAXN], tot = ;
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 = ; i <= n; ++i) {
if(in[i] == ) 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] == ) q.push(y);
}
} } int main() {
read(n); read(m);
for(int i = ; i <= m; ++i) {
int x, y;
read(x); read(y);
add(x, y);
in[y]++;
}
topsort();
for(int i = top; i >= ; --i) {
int x = b[i];
a[x][x] = ;
for(int j = lin[x]; j; j = e[j].next) {
a[x] |= a[e[j].y];
}
}
for(int i = ; i <= n; ++i) {
cout << a[i].count() << endl;
} return ;
}
AcWing 164. 可达性统计的更多相关文章
- AcWing:164. 可达性统计(拓扑排序 + 状态压缩算法)
给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条有向边. 输出格式 输出共N行,表示每个点能 ...
- AcWing P164 可达性统计 题解
Analysis 这道题我一开始想到的是传递闭包,但是时间复杂度是n³,也开不下30000*30000的数组,所以我想到了拓扑+状态压缩(bitset),从后往前找,把能到达的点能到哪里用位运算赋到上 ...
- 2101 可达性统计(拓扑排序/dfs+状态压缩)
[题目描述] 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. [题目链接] 2101 可达性统计 [算法] 拓扑排序之后逆序计算(感觉dfs更好写而且应 ...
- 「CH2101」可达性统计 解题报告
CH2101 可达性统计 描述 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到 ...
- 牛客 51011 可达性统计(拓扑排序,bitset)
牛客 51011 可达性统计(拓扑排序,bitset) 题意: 给一个 n个点,m条边的有向无环图,分别统计每个点出发能够到达的点的数量(包括自身) \(n,m\le30000\). 样例: 10 1 ...
- CH2101 可达性统计
题意 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 分析 有向无环图,可以按拓扑序逆序统计答案.可以用bitset维护可达性. 时间复杂度\(O(N ...
- CH 2101 - 可达性统计 - [BFS拓扑排序+bitset状压]
题目链接:传送门 描述 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条 ...
- CH2101 可达性统计(算竞进阶习题)
拓扑排序+状态压缩 考虑每一个点能够到达的所有点都是与该店相邻的点的后继节点,可知: 令f[u]表示u点可到达的节点个数,f[u]={u}与f[v](u, v)的并集 于是可以利用状态压缩,能够到达的 ...
- AcWing 160. 匹配统计 (哈希+二分) 打卡
阿轩在纸上写了两个字符串,分别记为A和B. 利用在数据结构与算法课上学到的知识,他很容易地求出了“字符串A从任意位置开始的后缀子串”与“字符串B”匹配的长度. 不过阿轩是一个勤学好问的同学,他向你提出 ...
随机推荐
- unity3d 学习笔记(三)
工作现场查看: 飞行模式: 按住鼠标右键 w s a d 围绕浏览当前视图, q e 上下浏览. 交模式下无效 需透视图 移动吸附:移动状态(w) ctrl+shif 移动吸附在其它物体上移动 顶点 ...
- 我已经写了DAL层的代码生成器
(1)创建您自己的解决方案 文件夹结构如以下: (2)编写代码: (要使用数据库 建议创建随意数据库就可以) 创建配置文件App.config代码例如以下: <?xml version=&quo ...
- 使用Visual Studio 2010 一步一步创建Powershell Module 和 Cmdlet
现在就用C#写一个超级简单的Module和Cmdlet 1. 在VS中创建一个Library的项目 文件->新建->项目->C#->Class Library 在这里给我们的C ...
- Android设备与外接U盘实现数据读取操作
现在越来越多手机支持OTG功能,通过OTG可以实现与外接入的U盘等USB设备实现数据传输.关于OTG,可以参考: http://blog.csdn.net/srw11/article/details/ ...
- Blend_ControlTemplate(Z)
原文:Blend_ControlTemplate(Z) 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010265681/article/deta ...
- 希尔伯特空间(Hilbert Space)
欧氏空间 → 线性空间 + 内积 ⇒ 内积空间(元素的长度,元素的夹角和正交) 内积空间 + 完备性 ⇒ 希尔伯特空间 0. 欧几里得空间 欧氏空间是一个特别的度量空间,它使得我们能够对其的拓扑性质, ...
- cocos2dx 2.2.3 xcode5.0,新mac项目错误
cocos2dx 2.2.3 xcode5.0,新建mac项目报错 Undefined symbols for architecture x86_64: "cocos2d::extens ...
- JS加载&解析XML文件,浏览器兼容
# JS加载XML,浏览器之间有差异,代码如下 this.createXMLDom = function() { var xmldoc; var xmlFile = "XXXXXXXXX. ...
- Alamofire - 优雅的处理 Swift 中的网络操作
网络处理,应该是我们平时开发的时候最常用到的操作.比如读取 JSON 数据,下载图片,这些操作都要和网络打交道,一个高效稳定的网络操作库对于提升我们日常的开发效率有着非常关键的作用.Alamofire ...
- 【转】关于在.Net开发中使用Sqlite的版本选择问题
如果一个.NET应用要自适应32位/64位系统,只需要在项目的“目标平台”设置为“Any CPU”.但是如果应用中使用了SQLite,情况就不同了. SQLite的.NET开发包来自是System.D ...