Description

Input

输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。

Output

输出一行一个整数,表示该图的连通数。

HINT

对于100%的数据,N不超过2000。

Solution

\(Tarjan\) 缩点 \(+\) 拓扑排序 \(+\) \(bitset\) 优化状压

显然对于每个强联通分量我们都要求出在新图上它能到达哪些点。

如何求呢?

法一: \(dfs\),对于每个强联通分量找一下它连出去的边能到达哪些联通块,统计答案即可。复杂度 \(O(n^2)\)。(只是口胡一下没有写这种方法如果写不出来别找我)

法二:我们定义数组 \(f[i][j]\) 表示能否从第 \(i\) 个连通分量到达第 \(j\) 个连通分量。因为值只能为 \(0/1\),我们用 \(bitset\) 来状压第二维。因为 \(f[j]=or(f[i]),j\;can\;go\;to\;i\),所以我们在新图上建立一张反图,拓扑排序,按照拓扑序即可求出每个点能到达哪些点。 复杂度 \(O(n^2/32)\)。

Code

#include<queue>
#include<bitset>
#include<cstdio>
#include<cctype>
#include<iostream>
#define N 2005
#define min(A,B) ((A)<(B)?(A):(B)) int ans;
char ch[N];
bool in[N];
int n,cnt,sum,tot;
int dfn[N],low[N];
std::bitset<N> f[N];
std::queue<int> topo;
int belong[N],deg[N];
int head[N],head2[N];
int stk[N],top,sze[N]; struct Edge{
int to,nxt;
}edge[N*N],edge2[N*N]; void add(int x,int y){
edge[++cnt].to=y;
edge[cnt].nxt=head[x];
head[x]=cnt;
} void add2(int x,int y){
edge2[++cnt].to=y;
edge2[cnt].nxt=head2[x];
head2[x]=cnt;
} int getint(){
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return x;
} void tarjan(int now){
dfn[now]=low[now]=++sum;
stk[++top]=now;in[now]=1;
for(int i=head[now];i;i=edge[i].nxt){
int to=edge[i].to;
if(!dfn[to]){
tarjan(to);
low[now]=min(low[now],low[to]);
}
else if(in[to])
low[now]=min(low[now],dfn[to]);
}
if(low[now]==dfn[now]){
int y; tot++;
do{
y=stk[top--];
belong[y]=tot;
sze[tot]++;
in[y]=0;
}while(y!=now);
}
} signed main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%s",ch);
for(int j=0;j<n;j++){
if(ch[j]=='0') continue;
add(i,j+1);
}
}
cnt=0;
for(int i=1;i<=n;i++){
if(!dfn[i])
tarjan(i);
}
for(int x=1;x<=n;x++){
for(int i=head[x];i;i=edge[i].nxt){
int to=edge[i].to;
if(belong[x]==belong[to]) continue;
deg[belong[x]]++;
add2(belong[to],belong[x]);
}
}
for(int i=1;i<=tot;i++)
f[i][i]=1;
for(int i=1;i<=tot;i++){
if(!deg[i])
topo.push(i);
}
while(topo.size()){
int u=topo.front();topo.pop();
for(int i=head2[u];i;i=edge2[i].nxt){
int to=edge2[i].to;
deg[to]--;
f[to]|=f[u];
if(!deg[to])
topo.push(to);
}
}
for(int i=1;i<=tot;i++){
for(int j=1;j<=tot;j++){
if(f[i][j])
ans+=sze[i]*sze[j];
}
}
printf("%d\n",ans);
return 0;
}

[JSOI2010] 连通数的更多相关文章

  1. BZOJ 2208: [Jsoi2010]连通数 tarjan bitset

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  2. bzoj2208:[Jsoi2010]连通数

    http://blog.csdn.net/u013598409/article/details/47037499 里面似乎有生成数据的... //我本来的想法是tarjan缩点之后然后将图遍历一遍就可 ...

  3. bzoj2208 [Jsoi2010]连通数(scc+bitset)

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1879  Solved: 778[Submit][Status ...

  4. BZOJ 2208: [Jsoi2010]连通数( DFS )

    n只有2000,直接DFS就可以过了... -------------------------------------------------------------------------- #in ...

  5. 2208: [Jsoi2010]连通数

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1371  Solved: 557[Submit][Status ...

  6. bzoj 2208 [Jsoi2010]连通数

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MB Description Input 输入数据第一行是图顶点的数量,一个正整数N ...

  7. 【BZOJ2208】[JSOI2010]连通数(Tarjan)

    [BZOJ2208][JSOI2010]连通数(Tarjan) 题面 BZOJ 洛谷 题解 先吐槽辣鸡洛谷数据,我写了个\(O(nm)\)的都过了. #include<iostream> ...

  8. 【BZOJ2208】[Jsoi2010]连通数 DFS

    [BZOJ2208][Jsoi2010]连通数 Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示 ...

  9. 【bzoj2208】[Jsoi2010]连通数

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2305  Solved: 989[Submit][Status ...

  10. 暴力【bzoj2208】: [Jsoi2010]连通数

    2208: [Jsoi2010]连通数 暴力过的. 没脸说... 正解好像是缩点+递推. 应该也不难写. code: #include <iostream> #include <cs ...

随机推荐

  1. .NET winform播放音频文件

    前提:最近要求做一个在winform端做一个音频文件播放的功能,至此,总结最近搜寻的相关资料. 一.微软提供了三种方式来播放音频文件 1.通过System.Media.SoundPlayer来播放 2 ...

  2. 小白的CTF学习之路2——二进制数据基础与运算(上)

    今天的第二更,被我拖到了傍晚,嘿嘿,二进制这方面让本就数学不好的我很头疼,所以研究了一段时间 在学习之前我们先了解几个问题: 32位是几个字节? 01011100对于十进制是多少? 00001111向 ...

  3. 软件推荐-c#绘图插件echart

    首先给出官网:http://echarts.baidu.com/examples/ 简单的教程:http://www.cnblogs.com/youmeng/p/4874897.html

  4. JavaScript基础视频教程总结(041-050章)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  5. 去掉input[type="number"]的默认样式

    input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{ -webkit-appearance: none !importa ...

  6. SWPU-ACM集训队周赛之组队赛(3-11) E题题解

    点这里去做题 %*c  读入时跳过一位,本题中即跳过"-"; #include<stdio.h> int run(int x) //判断闰年 { ; ==&&a ...

  7. 1.Spring框架入门案例

    一.简单入门案例 入门案例:IoC 1.项目创建与结构 2.接口与实现类 User.java接口 package com.jd.ioc; /** * @author weihu * @date 201 ...

  8. yesno孤立词识别kaldi脚本

    path.sh主要设定路径等 export KALDI_ROOT=`pwd`/../../.. [ -f $KALDI_ROOT/tools/env.sh ] && . $KALDI_ ...

  9. jQuery判断复选框checkbox的选中状态

    通过jQuery设置复选框为选中状态 复选框 <input type="checkbox"/> 错误代码: $("input").attr(&quo ...

  10. 分布式任务调度系统xxl-job源码探究(二、服务中心)

    接下来看下服务端代码 服务端源码 服务端通过管理quartz定时任务组件,分发任务 先从入口看起,由web.xml进入,可以看出,自己编写的代码从applicationcontext-xxl-job- ...