bitset在图论上的应用 传递闭包【例题gym 100342J & gym 100345H 】
来源:互联网 发布:菜鸟网络航空港区地址 编辑:程序博客网 时间:2024/06/06 12:30
bitset优点:
bitset在某些常数优化以及状态保存方面被称之为神器并不为过,主要表现在以下几个方面:1. 状态表示。试想,用一个数来表示状态的极限是64位,而bitset可以保存任意位二进制数,并且修改简单,统计方便,并且支持批量操作。2. 常数优化。图论的题,尤其涉及不带权的邻接图,算法经常动辄 n2,n3 ,这个时候我们可以用n个bitset存储每个点的邻接情况,并进行相应位操作,来替代直接遍历图的操作,经常可以将总复杂度降低为原来的1/32甚至还要少!3. 集合运算。交集按位与,并集按位或,取反直接flip,简直好用。4. 存储优化。一个bool型变量占一个字节(1byte),而bitset的一位只占1bit!某些内存卡得特别紧的情况可以试试(一般无卵用=_=
bitset基本操作表:
下面通过gym上的两道例题来了解一下bitset在图论上的应用
传送门:gym 100342J Triatrip
题意:
给一个邻接矩阵,求有多少条路径可以由A出发,经过B ,再经过C,最后回到A。
思路:
无论是用邻接矩阵乘法,还是跑flyod,都是 n3 的算法,而n≤1500,直接来果断TLE。
路径为A→B→C→A,是一个三元环,我们枚举每一条B→C路径,如果用n个bitset存储每一个点的出度与入度情况,然后将B的入度与C的出度相与,统计相与后的结果有多少个1,便是有多少个三元环,累计相与结果,答案即为累计值/3,复杂度下降为O(n2∗n/32),可以卡着时间过。
之所以要除以3的原因是环A→B→C→A包含了B→C→A→B,与C→A→B→C。
代码:
#include <bits/stdc++.h>using namespace std;#define ll __int64#define rep(i,k,n) for(int i=k;i<=n;i++)const int N=1510;char s[N][N];bitset<N>bit1[N], bit2[N], tmp;int n;int main(){ freopen("triatrip.in","r",stdin);//必须加上,不然得WA freopen("triatrip.out","w",stdout); scanf("%d", &n); rep(i, 0, n-1){ scanf("%s", s[i]); rep(j, 0, n-1){ if(s[i][j] == '+')bit1[i].set(j), bit2[j].set(i); } } ll ans=0; rep(i, 0, n-1){ rep(j, 0, n-1){ if(bit1[i][j]){ tmp = bit1[j] & bit2[i]; ans += tmp.count(); } } } printf("%I64d\n", ans / 3); return 0;}
传送门:gym 100345H Settling the Universe Up
题意:
输入一个邻接矩阵,统计图中有多少对点 ( u , v ) 是从u出发可以到达v,且u < v。
同时动态增删图中路径。
思路:
这题用线段树维护起来有些麻烦
先用bitset1存储每个点一次可到达点。
然后新开一组bitset2存储每个点的所有升序可到达点,bitset2可由bitset1进行或运算推出来,每次更新都重新推一次,直接暴力即可。不得不说bitset实在神奇。。不用bitset我都不知道怎么做这道题了。
代码:
#include <bits/stdc++.h>#define rep(i,k,n) for(int i=k;i<=n;i++)using namespace std;template<class T> void read(T&num) { char CH; bool F=false; for(CH=getchar();CH<'0'||CH>'9';F= CH=='-',CH=getchar()); for(num=0;CH>='0'&&CH<='9';num=num*10+CH-'0',CH=getchar()); F && (num=-num);}int stk[70], tp;template<class T> inline void print(T p) { if(!p) { puts("0"); return; } while(p) stk[++ tp] = p%10, p/=10; while(tp) putchar(stk[tp--] + '0'); putchar('\n');}const int N=210;int n, m, k, sum;bitset<N>b[N], bit[N];void update(){ rep(i, 1, n)bit[i].reset(); sum=0; for(int i=n; i>=1; i--){ bit[i].set(i); for(int j=1; j<i; j++){ if(b[j][i]) bit[j] |= bit[i]; } sum += bit[i].count(); }}int main(){ freopen("settling.in", "r", stdin); freopen("settling.out", "w", stdout); read(n),read(m); rep(i, 1, m){ int u, v; read(u),read(v); b[u].set(v); } update(); print(sum-n);//总数减去自环 read(k); while(k--){ char op[2];int u, v; scanf("%s%d%d",op, &u, &v); if(op[0] == '+'){ b[u].set(v); update(); print(sum-n); } else if(op[0] == '-'){ b[u].reset(v); update(); print(sum-n); } else{ if(bit[u].test(v))puts("YES"); else puts("NO"); } } return 0;}
0 0
- bitset在图论上的应用 传递闭包【例题gym 100342J & gym 100345H 】
- Gym 100342J & Gym 100345H (bitset在图论题的应用)
- Codeforces Gym 100342J Triatrip Bitset+枚举
- ACM bitset模板 Gym 100345H
- Gym-100342J Triatrip(求有向图三元环个数+bitset应用)
- Gym 100917J Judgement(dp+bitset)
- Codeforces Gym 100345H Settling the Universe Up Bitset+倒推
- PROBLEM_J: Gym 100345J - Zen Garden
- Gym 100917 J. Judgement
- Gym-100712J-Candy
- Gym 100712J Candy
- Gym 100637J
- Gym 101147.J
- Gym 101243.J
- Gym 101246.J
- Gym 101343.J
- Gym 101617J dp
- Gym
- wampserver显示红色、橙色的解决方案
- 前端练习4-立方体翻转效果
- IPC第四篇,Socket通信
- 微信自定义分享链接和图文
- [Android Studio 权威教程]断点调试和高级调试
- bitset在图论上的应用 传递闭包【例题gym 100342J & gym 100345H 】
- java关键字final、static 用法
- Python_排序算法实现
- 前端练习2-分页效果
- Android 退出登录账号后,极光推送还能推送消息到手机的问题的解决
- 你真的了解word-wrap和word-break的区别吗?
- JavaScript 模块化入门Ⅰ:理解模块
- Linux命令之"touch"
- FastSlam在ubuntu Qt下的使用问题