牛客 51011 可达性统计(拓扑排序,bitset)
牛客 51011 可达性统计(拓扑排序,bitset)
题意:
给一个 n个点,m条边的有向无环图,分别统计每个点出发能够到达的点的数量(包括自身) \(n,m\le30000\).
样例:
10 10
3 8
2 3
2 5
5 9
5 9
2 3
3 9
4 8
2 10
4 9
题解:
想要统计每个点能够出发到达的点数量,如果一个一个点来搜索计算的话,那么复杂度将会变成 \(O(n^2)\),所以我们要换个角度思考,在访问每一个点的时候,考虑由哪个点可以到达它,所以我们可以反向建边,按照图拓扑排序的顺序进行访问,将自身的贡献传递给自己的临点。
但是计算贡献的时候,要考虑重复的计算,如下图(已经是反向建边了),D点访问过后,A和C点的贡献都为2,如果再一次 访问完A和C后,B的贡献就会变成5,显然的多计算了一次D的贡献。

在这里我们可以引入二进制位来避免这种情况发生,也就是用一个数字的二进制数来表示一个点的贡献,这个二进制数第i位为 \(i\),则代表这个点可以到达 \(i\),设上图的A,B,C,D点分别为点1,2,3,4.那么起始的点1,2,3,4的贡献可以记录为 2,4,8,16.其实是他们的二进制位的第一位,第二位,第三位,第四位设位1了,那么点A的贡献将为 \(val_A | val_D\)=2|16 =18,C的贡献为 \(valD|valC\)=16|8 =24.这样点B的贡献将为\(valA|valB|valC\)=18 | 24 | 4=30.这代表着B点可以到达第一个点,第二个,第三个点,第四个点。由于或运算的关系,D的贡献不会重复计算。不过这里还有一个问题是由于数据规模的原因我们不能直接用数字来表示二进制位的贡献,因此我们要引入bitset。
bitset
bitset是C++提供的一个模板类,原型为 template<size_t N>class bitset。参数是bitset的二进制位的个数。
bitset<6>B;//这里我们定义了一个长度为40的bitset,它的每一位都是bool类型,占内存1bit
B[2]=1;//每一个位置都可以通过下标来访问以及进行修改。
bitset<6>C(string("101"));//我们还可以用一个只包含0和1字符的string类来初始话这个bitset,
//这里bitset的值依次为000101.是string的长度超过bitset的长度,字符串后面的字符会被舍弃掉。
C.count();//输出C种为1的bool元素的个数。这里结果为2.
C.reset();//将C的所有的位数全部置为1.
B = B|C;//同时支持 或,与,异或 这种位运算。要保证他们的长度要相同。
有了bitset的这些操作后,思路就很明显了,按照拓扑排序的顺序访问,每一次用bitset来传递贡献,最后输出每个bitset种为1的bool元素的个数。
struct P{int x;int y;P(){}P(int _x,int _y):x(_x),y(_y){}};
vector<int>ege[maxn];
bitset<maxn>cnt[maxn];
set<P>S;
int in[maxn]={0};
bool operator<(const P a,const P b){//
if(a.x==b.x)return a.y<b.y;
return a.x<b.x;
}
void solve(){
int n,m;scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int x,y;scanf("%d %d",&x,&y);
if(S.count(P(x,y)))continue;//将重复元素筛掉。
S.insert(P(x,y));
++in[x];
ege[y].push_back(x);
}
for(int i=1;i<=n;i++)cnt[i][i]=1;//将第i个bitset的第i位初始化1.
queue<int>q;
for(int i=1;i<=n;i++){
if(in[i]==0)q.push(i);
}
while(!q.empty()){
int u = q.front();
q.pop();
for(int v:ege[u]){
--in[v];
cnt[v] = cnt[v]|cnt[u];//用或运算将u的贡献传递给v。
if(in[v]==0)q.push(v);
}
}
for(int i=1;i<=n;i++)printf("%d\n",cnt[i].count());
}
牛客 51011 可达性统计(拓扑排序,bitset)的更多相关文章
- [LOJ 3101] [Luogu 5332] [JSOI2019]精准预测(2-SAT+拓扑排序+bitset)
[LOJ 3101] [Luogu 5332] [JSOI2019]精准预测(2-SAT+拓扑排序+bitset) 题面 题面较长,略 分析 首先,发现火星人只有死和活两种状态,考虑2-SAT 建图 ...
- Acwing-164-可达性统计(拓扑排序, 位运算统计)
链接: https://www.acwing.com/problem/content/166/ 题意: 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量. 思路: 先拓扑排序求 ...
- NOIP 车站分级 (luogu 1983 & codevs 3294 & vijos 1851) - 拓扑排序 - bitset
描述 一条单向的铁路线上,依次有编号为 1, 2, ..., n 的 n 个火车站.每个火车站都有一个级别,最低为 1 级.现有若干趟车次在这条线路上行驶,每一趟都满足如下要求:如果这趟车次停靠了火车 ...
- [BZOJ4484][JSOI2015]最小表示[拓扑排序+bitset]
题意 给你一个 \(n\) 个点 \(m\) 条边的 \(\rm DAG\) ,询问最多能够删除多少条边,使得图的连通性不变 \(n\leq 3\times 10^4\ ,m\leq 10^5\) . ...
- BZOJ4484 JSOI2015最小表示(拓扑排序+bitset)
考虑在每个点的出边中删除哪些.如果其出边所指向的点中存在某点能到达另一点,那么显然指向被到达点的边是没有用的.于是拓扑排序逆序处理,按拓扑序枚举出边,bitset维护可达点集合即可. #include ...
- BZOJ5109 CodePlus 2017大吉大利,晚上吃鸡!(最短路+拓扑排序+bitset)
首先跑正反两遍dij求由起点/终点到某点的最短路条数,这样条件一就转化为f(S,A)*f(T,A)+f(S,B)*f(T,B)=f(S,T).同时建出最短路DAG,这样图中任何一条S到T的路径都是最短 ...
- CH 2101 - 可达性统计 - [BFS拓扑排序+bitset状压]
题目链接:传送门 描述 给定一张N个点M条边的有向无环图,分别统计从每个点出发能够到达的点的数量.N,M≤30000. 输入格式 第一行两个整数N,M,接下来M行每行两个整数x,y,表示从x到y的一条 ...
- BZOJ 4484: [Jsoi2015]最小表示(拓扑排序+bitset)
传送门 解题思路 \(bitset\)维护连通性,给每个点开个\(bitset\),第\(i\)位为\(1\)则表示与第\(i\)位联通.算答案时显然要枚举每条边,而枚举边的顺序需要贪心,一个点先到达 ...
- 牛客 82E 无向图中的最短距离 (bitset,bfs)
有一个n个点的无向图,有m次查询,每次查询给出一些(xi,yi) 令dist(x,y)表示x和y点在图中最短距离,dist(x,x)=0,如果x,y不连通则dist(x,y) = inf 每次查询图中 ...
随机推荐
- js获取url并截取相应的字段,js解决url获取中文字段乱码问题
相信url截取信息是一个很常用的小功能页面跳转传参的时候可以在A页面的url挂一些参数到B页面获取正常的页面传参都是以数字和英文为主正常情况下中文获取的时候是有乱码的所谓上有政策下有对策一个正常的ur ...
- C++ 线性筛素数
今天要写一篇亲民的博客了,尽力帮助一下那些不会线性筛素数或者突然忘记线性筛素数的大佬. 众所周知,一个素数的倍数肯定不是素数(废话).所以我们可以找到一个方法,普通的筛法(其实不算筛,普通的是判断一个 ...
- MemoryCacheHelper与RedisCacheHelper缓存集成与测试笔记
因为每次在新项目中需要花费大量时间在基础类库搬移.调试.为了节省时间(偷懒)就将MemoryCacheHelper/RedisHelper进行了封装 本次是关于缓存方面记录,源码请参考(包含Redis ...
- 题解 CF917D 【Stranger Trees】
生成树计数问题用矩阵树定理来考虑. 矩阵树定理求得的为\(\sum\limits_T\prod\limits_{e\in T}v_e\),也就是所有生成树的边权积的和. 这题边是不带权的,应用矩阵树定 ...
- Dubbo的负载均衡算法源码分析
Dubbo提供了四种负载均衡:RandomLoadBalance,RoundRobinLoadBalance,LeastActiveLoadBalance,ConsistentHashLoadBala ...
- centos7.5安装gdal编译环境
安装准备的环境: 名称 类型与版本 软件连接 服务器 linux-centos7.5 jdk 1.8.0_25 ant 1.9.14 http://mirror.bit.edu.cn/apac ...
- scp的使用以及cp的对比
scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.可能会稍微影响一下速度.当你服务器 ...
- RecyclerView设置空视图
RecyclerView貌似不能直接设置空视图,所以可以自定义一个RecyclerView继承自RecyclerView并设置一个数据监听者监视数据状态. MyCyclerView.java pack ...
- OceanBase安装和使用
链接 https://mp.weixin.qq.com/s?spm=a2c6h.12873639.0.0.41f92c9bH5FL2Y&__biz=MzU3OTc2MDQxNg==&m ...
- 使用 expect 重启失败的 git pull/push 操作
问题的提出 最近使用 github 上传.下载项目代码时,经常会卡很久,有时候在命令行打了 git push 然后就去上厕所了,结果等我回来的时候,发现 push 早已经失败了,还得重新提交一下.如果 ...