BZOJ2208 [Jsoi2010]连通数[缩点/Floyd传递闭包+bitset优化]
显然并不能直接dfs,因为$m$会非常大,复杂度就是$O(mn)$;
这题有三种做法,都用到了bitset的优化。第二种算是一个意外的收获,之前没想到竟然还有这种神仙操作。。
方法一:缩点+DAG上bitset优化的统计
做有向图连通问题上来先看可不可以缩点首先一个环内点是可以相互连通的,又发现DAG也许方便统计,于是缩点。。然后变成一张DAG,只要统计每个点可以往后走到的所有点权(指该环包含的点数)的和。并不好直接把后继全加上去,因为会有点被重复统计。为了避免重复统计,只要直接每个点开一个bitset,表示他能走到哪些点,这样dp的时候直接对儿子取or就可以了,然后再统计,不会重复。复杂度$O(\frac{mn}{32})$。实际上是可以卡过去的。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<bitset>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+;
struct thxorz{
int to[N*N],nxt[N*N],head[N],tot;
inline void add(int x,int y){to[++tot]=y,nxt[tot]=head[x],head[x]=tot;}
}G1,G2;
int from[N*N];
char s[N];
int n,m,ans;
#define y G1.to[j]
int dfn[N],low[N],tim,stk[N],instk[N],bel[N],sum[N],val[N],Top;
void tarjan(int x){
dfn[x]=low[x]=++tim,stk[++Top]=x,instk[x]=;
for(register int j=G1.head[x];j;j=G1.nxt[j]){
if(!dfn[y])tarjan(y),MIN(low[x],low[y]);
else if(instk[y])MIN(low[x],dfn[y]);
}
if(dfn[x]==low[x]){
int tmp;
do instk[tmp=stk[Top--]]=,bel[tmp]=x,++sum[x];while(tmp^x);
}
}
#undef y
#define y G2.to[j]
bitset<N> S[N];
void dp(int x){
if(val[x])return;
S[x][x]=;
for(register int j=G2.head[x];j;j=G2.nxt[j])dp(y),S[x]|=S[y];
for(register int i=;i<=n;++i)if(S[x][i])val[x]+=sum[i];
val[x]=val[x]*sum[x];
}
#undef y
int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n);
for(register int i=;i<=n;++i){
scanf("%s",s+);
for(register int j=;j<=n;++j)if(i^j&&s[j]=='')G1.add(i,j),from[G1.tot]=i;
}
for(register int i=;i<=n;++i)if(!dfn[i])tarjan(i);
for(register int t=,x,y;t<=G1.tot;++t){
x=from[t],y=G1.to[t];
if(bel[x]^bel[y])G2.add(bel[x],bel[y]);
}
for(register int i=;i<=n;++i)dp(i),ans+=val[i];
printf("%d\n",ans);
return ;
}
方法二:Floyd传递闭包+bitset优化
这个优化真是妙啊,之前学Floyd都没想过这个优化。`````
连通性可以用二元逻辑关系表示,也就是可以用Floyd来做传递闭包。具体来说,就是设$f_{i,j}=0/1$表示$i$到$j$是否可达。然后转移的话是$\text{f[i][j]|=f[i][k]&f[k][j]}$。
注意这个转移。$f_{i,j}$相当于看成对于$i$点,用一个bitset表示他到$1\sim n$各点的可达性。
再观察,$f[i][k]$值已经是定的了,如果是$0$就不转移了,是$1$的话,对于每一位$j$,只要用$f[k]$对应的$j$位or一下就可以了。并且$f[i][k]$在本次转移中是不会变的。
所以,直接用bitset整体进行or操作就行了。$O(\frac{n^3}{32})$。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<bitset>
#define mst(x) memset(x,0,sizeof x)
#define dbg(x) cerr << #x << " = " << x <<endl
#define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,):;}
template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,):;}
template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=+;
bitset<N> f[N];
int n,ans;
char s[N]; int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout);
read(n);
for(register int i=;i<=n;++i){
scanf("%s",s+);
for(register int j=;j<=n;++j)f[i][j]=s[j]==''||i==j;
}
for(register int k=;k<=n;++k)
for(register int i=;i<=n;++i)
if(f[i][k])f[i]|=f[k];
for(register int i=;i<=n;++i)ans+=f[i].count();
return printf("%d\n",ans),;
}
方法三:暴力BFS+bitset标记松弛点(手写警告)
对每一个点,直接开始BFS,然后这个做法时间瓶颈在于每次都要枚举到所有边,那么我么尽量让他BFS时候从松弛点去走没有被访问过的点,避免走路径通向访问过的点的。可以用bitset维护目前所有点哪些没有被访问过,每个节点再开一个bitset表示他通往哪些点,每次BFS松弛的时候,把两者and一下,这样所有的$1$位就是没有访问过的,仅取出这些$1$,访问之即可。这样,就使得走过的边数量与点数相同,复杂度就降成了$O(n(\frac{n^2}{32}+n))$。不过,这种方法由于要取出$1$,如果直接对bitset每一位直接检验,复杂度就又回去了,而STL的bitset太垃圾没有这个取$1$复杂度和$1$数量相同的方法,所以我们要手写bitset。。。这种方法是yql讲过的,由于我太菜了,所以我不会写,实际要咕咕咕。

BZOJ2208 [Jsoi2010]连通数[缩点/Floyd传递闭包+bitset优化]的更多相关文章
- [bzoj2208][Jsoi2010]连通数_bitset_传递闭包floyd
连通数 bzoj-2208 Jsoi-2010 题目大意:给定一个n个节点的有向图,问每个节点可以到达的点的个数和. 注释:$1\le n\le 2000$. 想法:网上有好多tarjan+拓扑序dp ...
- 2018.09.11 bzoj2208: [Jsoi2010]连通数(bitset+floyd)
传送门 听说正解是缩点+dfs? 直接bitset优化floyd传递闭包就行了.(尽管时间复杂度是假的O(n3/32)" role="presentation" styl ...
- BZOJ2208: [Jsoi2010]连通数(tarjan bitset floyd)
题意 题目链接 Sol 数据水的一批,\(O(n^3)\)暴力可过 实际上只要bitset优化一下floyd复杂度就是对的了(\(O(\frac{n^3}{32})\)) 还可以缩点之后bitset维 ...
- bzoj2208 [Jsoi2010]连通数(scc+bitset)
2208: [Jsoi2010]连通数 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1879 Solved: 778[Submit][Status ...
- [BZOJ2208]:[Jsoi2010]连通数(暴力 or bitset or 塔尖?)
题目传送门 题目描述 度量一个有向图连通情况的一个指标是连通数,指图中可达顶点对的个数. 在上图中,顶点1可以到达1.2.3.4.5. 顶点2可以到达2.3.4.5. 顶点3可以到达3.4.5. 顶点 ...
- [BZOJ2208][Jsoi2010]连通数 暴力枚举
Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. Output 输出一行一个整数,表示该图 ...
- BZOJ2208: [Jsoi2010]连通数
tarjan缩点后拓扑排序,每一个点用一个bitset记录哪些点能到达它. PS:数据太水,暴力能过. #include<bits/stdc++.h> using namespace st ...
- POJ 3275 Ranking the cows ( Floyd求解传递闭包 && Bitset优化 )
题意 : 给出 N 头牛,以及 M 个某些牛之间的大小关系,问你最少还要确定多少对牛的关系才能将所有的牛按照一定顺序排序起来 分析 : 这些给出的关系想一下就知道是满足传递性的 例如 A > B ...
- HDU 5036 Explosion (传递闭包+bitset优化)
<题目链接> 题目大意: 一个人要打开或者用炸弹砸开所有的门,每个门后面有一些钥匙,一个钥匙对应一个门,告诉每个门里面有哪些门的钥匙.如果要打开所有的门,问需要用的炸弹数量为多少. 解题分 ...
随机推荐
- vue项目中的父子组件之间的传值。
首先说一下父子组件就是在一个vue文件中引入另一个vue文件,被引入vue文件就是子组件,引入vue文件的vue文件就是父组件.而在父组件中是不能直接调用子组件中的变量值的.下面详细说一下,父子组件之 ...
- fastadmin添加定时任务
安装定时任务插件后 需要在crontab -e 中添加一条记录 * * * * * /usr/bin/php /var/www/yoursitepath/public/index.php /addon ...
- mybatis 的一对一关联查询association
现在项目的列表查询数据需要查一个总数count, 如果直接写在同一个sql里面,会导致查询速度很慢, 因此,想到使用关联查询,例子如下: 附上代码: 其中遇到的坑哟: 1.association中的s ...
- ES-实战
一.环境准备 操作系统:mac 依赖的软件:JDK1.8.Postman.NodeJs6.0以上.Maven.Idea ES下载:Elastic官方网站: http://www.elastic.co ...
- 使用haystack实现django全文检索搜索引擎功能
前言 django是python语言的一个web框架,功能强大.配合一些插件可为web网站很方便地添加搜索功能. 搜索引擎使用whoosh,是一个纯python实现的全文搜索引擎,小巧简单. 中文搜索 ...
- Spring实战(五)Spring中条件化地创建bean
1.@Conditional 为生成bean设置条件 Spring 4中引入了一个新的注解---@Conditional,它用在有@Bean的方法上. 如果给定条件计算结果为true,Spring会创 ...
- java实现4种内部排序
两种插入类排序: 直接插入排序: public static void insertSort(int[] arr, int len){ for(int i=1; i<len; i++){ int ...
- Nopcommerce 项目添加插件
插件是用来扩展nopCommerce功能的.nopCommerce拥有多种类型的插件.例如:支付方式(PayPal),税务机构,送货方式计算方法(UPS, USP, FedEx),小部件(如“在线聊天 ...
- Git详细操作
Git详细操作 一.本地配置 1公钥钥配置 1.参考帮助文档:https://gitee.com/help/ 仓库管理 =公钥管理 =生成/添加SSH公钥 ssh-keygen -t rsa -C & ...
- ES6模块化及优点,简单案例让你秒懂
模块化:模块是一个文件 好处: 1.减少命名冲突 2.避免引入时的层层依赖 3.可以提升执行效率 **第一种方法************ ...