BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset
BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset
Description

Input
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。
Output
输出一行一个整数,表示该图的连通数。
Sample Input
010
001
100
Sample Output
HINT
对于100%的数据,N不超过2000。
直接缩点+拓扑排序统计答案即可。
每步转移是O(n)的,可以用bitset优化到O(n/32)。
其实就是想练习一下手写bitset,显然没有STL的块。
总时间复杂度O(nnm/32)
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 2050
#define M 4000500
#define _min(x,y) ((x)<(y)?(x):(y))
typedef unsigned int ut;
const int M1=65535;
inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rc() {
char s=nc();
while(s<'0'||s>'1') s=nc();
return s=='1';
}
int rd() {
int x=0; char s=nc();
while(s<'0'||s>'9') s=nc();
while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
return x;
}
int n,block,h[1<<16];
int g1(unsigned int x) {
return h[x>>16]+h[x&M1];
}
struct Bitset {
ut b[70];
int get_num() {
int i,re=0;
for(i=1;i<=block;i++) re+=g1(b[i]);
return re;
}
Bitset operator | (const Bitset &x) const {
Bitset re; int i;
for(i=1;i<=block;i++) re.b[i]=(b[i]|x.b[i]);
return re;
}
}f1[N],f2[N];
int head[N],to[M],nxt[M],in[N],Q[N],l,r;
int S[N],bel[N],siz[N],L[80],R[80],pos1[N],pos2[N],dfn[N],low[N],tot,scc,top,ins[N],xx[M],yy[M],qwq,cnt;
inline void add(int u,int v) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
void dfs(int x) {
int i;
dfn[x]=low[x]=++tot; S[++top]=x; ins[x]=1;
for(i=head[x];i;i=nxt[i]) {
if(!dfn[to[i]]) {
dfs(to[i]);
low[x]=_min(low[x],low[to[i]]);
}else if(ins[to[i]]) {
low[x]=_min(low[x],dfn[to[i]]);
}
}
if(dfn[x]==low[x]) {
int t=S[top--]; ins[t]=0;
bel[t]=++scc; f2[scc]=f1[t];
siz[scc]=1;
while(t!=x) {
t=S[top--]; ins[t]=0;
bel[t]=scc; f2[scc]=f2[scc]|f1[t];
siz[scc]++;
}
}
}
int main() {
n=rd();
register int i,j;
int x;
for(i=1;i<=M1;i++) h[i]=h[i>>1]+(i&1);
block=n/32;
for(i=1;i<=block;i++) {
L[i]=R[i-1]+1; R[i]=i*32;
for(j=L[i];j<=R[i];j++) {
pos1[j]=i; pos2[j]=j-L[i];
}
}
if(R[block]!=n) {
L[block+1]=R[block]+1; R[++block]=n;
for(i=L[block];i<=n;i++) pos1[i]=block,pos2[i]=i-L[block];
}
for(i=1;i<=n;i++) {
for(j=1;j<=n;j++) {
x=rc();
if(x) f1[i].b[pos1[j]]|=(1<<pos2[j]),add(i,j),xx[++qwq]=j,yy[qwq]=i;
}
f1[i].b[pos1[i]]|=(1<<pos2[i]);
}
for(i=1;i<=n;i++) {
if(!dfn[i]) dfs(i);
}
memset(head,0,sizeof(head)); cnt=0;
for(i=1;i<=qwq;i++) {
if(bel[xx[i]]!=bel[yy[i]]) {
add(bel[xx[i]],bel[yy[i]]); in[bel[yy[i]]]++;
}
}
for(i=1;i<=scc;i++) {
if(!in[i]) Q[r++]=i;
}
int ans=0;
while(l<r) {
x=Q[l++]; ans+=siz[x]*f2[x].get_num();
for(i=head[x];i;i=nxt[i]) {
in[to[i]]--;
f2[to[i]]=f2[to[i]]|f2[x];
if(in[to[i]]==0) Q[r++]=to[i];
}
}
printf("%d\n",ans);
}
BZOJ_2208_[Jsoi2010]连通数_强连通分量+拓扑排序+手写bitset的更多相关文章
- BZOJ_3887_[Usaco2015 Jan]Grass Cownoisseur_强连通分量+拓扑排序+DP
BZOJ_3887_[Usaco2015 Jan]Grass Cownoisseur_强连通分量+拓扑排序+DP Description In an effort to better manage t ...
- poj 2762(强连通分量+拓扑排序)
题目链接:http://poj.org/problem?id=2762 题意:给出一个有向图,判断任意的两个顶点(u,v)能否从u到达v,或v到达u,即单连通,输出Yes或No. 分析:对于同一个强连 ...
- BZOJ1924:[SDOI2010]所驼门王的宝藏(强连通分量,拓扑排序)
Description Input 第一行给出三个正整数 N, R, C. 以下 N 行,每行给出一扇传送门的信息,包含三个正整数xi, yi, Ti,表示该传送门设在位于第 xi行第yi列的藏宝宫室 ...
- 2019ICPC(银川) - Delivery Route(强连通分量 + 拓扑排序 + dijkstra)
Delivery Route 题目:有n个派送点,x条双向边,y条单向边,出发点是s,双向边的权值均为正,单向边的权值可以为负数,对于单向边给出了一个限制:如果u->v成立,则v->u一定 ...
- CDOJ 图论专题 A.不是图论 强连通分量+拓扑排序 经典
题目链接 在其中纠错第一次wa代码 #include <cstdio> #include <cstring> #include <cstdlib> #includ ...
- POJ 2762 Going from u to v or from v to u?(强连通分量+拓扑排序)
职务地址:id=2762">POJ 2762 先缩小点.进而推断网络拓扑结构是否每个号码1(排序我是想不出来这点的. .. ).由于假如有一层为2的话,那么从此之后这两个岔路的点就不可 ...
- BZOJ_2438_[中山市选2011]杀人游戏 _强连通分量
BZOJ_2438_[中山市选2011]杀人游戏 _强连通分量 Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手.警察能够对每一个人 ...
- BZOJ_2140_稳定婚姻_强连通分量
BZOJ_2140_稳定婚姻_强连通分量 Description 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚 姻问题的专家认为,是与简化离 ...
- BZOJ_1916_[Usaco2010 Open]冲浪_分层图+拓扑排序+DP
BZOJ_1916_[Usaco2010 Open]冲浪_分层图+拓扑排序+DP Description 受到秘鲁的马丘比丘的新式水上乐园的启发,Farmer John决定也为奶牛们建 一个水上乐园. ...
随机推荐
- vmware克隆一台机器后修改etho
1 vi /etc/udev/rules.d/70-persistent-net.rules 2 注释NAME="eth0"的内容 3 将NAME="eth1" ...
- C++ "#"的作用和使用方法
本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/48879093 1 #和##的作用和使用 ...
- Openlayers中layer介绍
1.base layers & overlay layers base layer:最底层的layer,其它的图层是在他之上,最先增加的图层默认作为base layer. overlay la ...
- 04 svn设置开机启动
一:设置开机启动[dos命令] 格式: sc create 服务名称 binPath=空格"安装目录/svnserve.exe -r 版本库地址目录 --service" star ...
- Andorid——ubuntu下的 NDK / JNI
之前一直有接触源代码里面的JNI体系,知道个大概,仅仅管调进了哪个C/C++的接口,如今记录学习下. 撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/ ...
- js怎么限制文本框input只能输入数字
1.说明 本篇文章介绍怎么使用js限制文本框只能输入数字 2.HTML代码 <!DOCTYPE html> <html xmlns="http://www.w3.org/1 ...
- yuicompressor
yui/yuicompressor: YUI Compressor https://github.com/yui/yuicompressor YUI Compressor 详细介绍 YUI ...
- ByteBuf(图解1)
目录 源码工程 写在前面 Netty ByteBuf 优势 手动获取与释放ByteBuf 自动获取和释放 ByteBuf 方式一:TailHandler 自动释放 方式二:SimpleChannelI ...
- send data to Flume client-sdk flume使用之httpSource
https://flume.apache.org/FlumeDeveloperGuide.html#client-sdk flume使用之httpSource - CSDN博客 https://blo ...
- Eclipse中同时打开多个Console
实现方法: 1.点击Open Console案例下拉三角,选择New Console View. 2.点击Pin Console按钮將两个控制台同时固定住. 3.点击Display Selected ...