Gym 100342J & Gym 100345H (bitset在图论题的应用)
2015-08-30 23:24
357 查看
bitset
bitset在某些常数优化以及状态保存方面被称之为神器并不为过,主要表现在以下几个方面:1. 状态表示。试想,用一个数来表示状态的极限是64位,而bitset可以保存任意位二进制数,并且修改简单,统计方便,并且支持批量操作。
2. 常数优化。图论的题,尤其涉及不带权的邻接图,算法经常动辄 n2,n3n^2,n^3 ,这个时候我们可以用n个bitset存储每个点的邻接情况,并进行相应位操作,来替代直接遍历图的操作,经常可以将总复杂度降低为原来的1/32甚至还要少!
3. 集合运算。交集按位与,并集按位或,取反直接flip,简直好用。
4. 存储优化。一个bool型变量占一个字节(1byte),而bitset的一位只占1bit!某些内存卡得特别紧的情况可以试试(一般无卵用=_=
Gym 100342J Triatrip
题意:
给一个邻接矩阵,求有多少条路径可以由A出发,经过B ,再经过C,最后回到A。思路:
无论是用邻接矩阵乘法,还是跑flyod,都是 n3n^3 的算法,而n≤1500n\leq 1500,直接来果断TLE。路径为A→B→C→A,是一个三元环,我们枚举每一条B→C路径,如果用n个bitset存储每一个点的出度与入度情况,然后将B的入度与C的出度相与,统计相与后的结果有多少个1,便是有多少个三元环,累计相与结果,答案即为累计值/3,复杂度下降为O(n2∗n/32)O(n^2*n/32),可以卡着时间过。
之所以要除以3的原因是环A→B→C→A包含了B→C→A→B,与C→A→B→C。
代码:
[code]/* * @author FreeWifi_novicer * language : C++/C */ #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<string> #include<map> #include<set> #include<vector> #include<queue> #include<bitset> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define mp make_pair #define pb push_back typedef long long lint; typedef long long ll; typedef long long LL; const int maxn = 1505 ; bitset<maxn> bit1[maxn] , bit2[maxn] , tmp ; char s[maxn] ; int G[maxn][maxn] ; int main(){ freopen("triatrip.in","r",stdin); freopen("triatrip.out","w",stdout); //freopen("input.txt","r",stdin); int n ; cin >> n ; for( int i = 0 ; i < maxn ; i++ ) bit1[i].reset() , bit2[i].reset() ; for( int i = 0 ; i < n ; i++ ){ scanf( "%s" , s ) ; for( int j = 0 ; j < n ; j++ ){ if( s[j] == '+' ){ G[i][j] = 1 ; bit1[i].set(j) ; bit2[j].set(i) ; } } } lint ans = 0 ; for( int i = 0 ; i < n ; i++ ){ for( int j = 0 ; j < n ; j++ ){ if( i == j ) continue ; if( G[i][j] ){ tmp = bit1[j] & bit2[i] ; ans += tmp.count() ; } } } cout << ans / 3 << endl; return 0; }
Gym 100345H Settling the Universe Up
题意:
输入一个邻接矩阵,统计图中有多少对点 ( u , v ) 是从u出发可以到达v,且u < v。同时动态增删图中路径。
思路:
看到这种问题,又想到了线段树,怒想半小时无解,卒。先用bitset1存储每个点一次可到达点。
然后新开一组bitset2存储每个点的所有升序可到达点,bitset2可由bitset1进行或运算推出来,每次更新都重新推一次,直接暴力即可。
不得不说bitset实在神奇。。不用bitset我都不知道怎么做这道题了。
代码:
[code]/* * @author FreeWifi_novicer * language : C++/C */ #include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<string> #include<map> #include<set> #include<vector> #include<queue> #include<bitset> using namespace std; #define clr( x , y ) memset(x,y,sizeof(x)) #define cls( x ) memset(x,0,sizeof(x)) #define mp make_pair #define pb push_back typedef long long lint; typedef long long ll; typedef long long LL; const int maxn = 205 ; bitset<maxn> bit[maxn] , bits[maxn] ; int n , sum , m ; void update(){ for( int i = 1 ; i <= n ; i++ ) bits[i].reset() ; sum = 0 ; for( int i = n ; i > 0 ; i-- ){ bits[i].set(i); for( int j = 1 ; j < i ; j++ ){ if( bit[j][i] ) bits[j] |= bits[i] ; } sum += bits[i].count() ; } } int main(){ // freopen("input.txt","r",stdin); freopen("settling.in","r",stdin); freopen("settling.out","w",stdout); cin >> n >> m ; for( int i = 1 ; i <= n ; i++ ) bit[i].reset() , bits[i].reset() ; for( int i = 0 ; i < m ; i++ ) { int u , v ; scanf( "%d%d" , &u , &v ) ; bit[u].set(v); } sum = 0 ; update() ; printf( "%d\n" , sum - n ) ; int k ; cin >> k ; while( k-- ){ char op[2] ; int u , v ; scanf( "%s%d%d" , op , &u , &v ) ; if( op[0] == '+' ){ bit[u].set(v) ; update() ; printf( "%d\n" , sum - n ) ; } else if( op[0] == '-' ){ bit[u].reset(v) ; update() ; printf( "%d\n" , sum - n ) ; } else { if( bits[u].test(v) ) puts( "YES" ) ; else puts( "NO" ) ; } } return 0; }
相关文章推荐
- 静态库的制作
- IntelliJ IDEA 在使用manven后的纠结(每次修改代码都要重启tomcat才能看效果吗?),请各位大侠来看看问题
- Java多线程之可见性与原子性——synchronized VS volatile
- Struts2 框架的意义
- 如何简单地在浏览器中使用阿里云的文件上传功能?
- 一致性哈希算法及其在分布式系统中的应用 作者 张洋
- HDU 1874 畅通工程续
- jdk7之java.lang.invoke.MethodHandle
- Sql-性能优化
- 【写一个自己的js库】 4.完善跨浏览器事件操作
- 理解Load Average做好压力测试
- display the contents of a PEM formatted certificate under Linux, using openssl:
- 如何跨 frame 获取页面元素和函数
- hdu 3524 Perfect Squares 推公式求逆元
- 问题
- 3D图像算法
- svg画大白
- 数据库连接全接触
- UML序列图总结
- mysql authorization check