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. Alpha 冲刺 (5/10)

    队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助前后端接口的开发 测试项目运行的服务器环 ...

  2. # 2019-2020-3 《Java 程序设计》实验一:Java开发环境的熟悉

    2019-2020-3 <Java 程序设计>实验一:Java开发环境的熟悉-------1 一.实验要求: 1 建立"自己学号exp1"的目录 2 在"自己 ...

  3. shell脚本学习-变量

    跟着RUNOOB网站的教程学习的笔记 shell变量 shell变量的命名 定义变量时,变量名不加美元符号($,PHP语言中需要),如: name="runoob" 注意,变量名与 ...

  4. nginx unit 的使用

    参考文档:http://unit.nginx.org/configuration/# 安装 可以参考这两篇博客: https://www.cnblogs.com/wang-li/p/9694391.h ...

  5. 51nod1683

    代码参考:http://blog.csdn.net/sdfzyhx/article/details/74359927 //dp[i][j][k]表示到了第i列,最下边的点最短路为j,剩下的点之间的关系 ...

  6. TabLoaout简单框架

    import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design. ...

  7. 再谈控制 cxGrid 的行列颜色

    1. [转]CxGrid 改变某行或单元格的颜色 (2016-01-19 09:37:19) 转载▼ 标签: it delphi 分类: Delphi 一个表(T)的结构结构如下. ID Test 1 ...

  8. Android开发 - ImageView加载Base64编码的图片

    在我们开发应用的过程中,并不是所有情况下都请求图片的URL或者加载本地图片,有时我们需要加载Base64编码的图片.这种情况出现在服务端需要动态生成的图片,比如: 二维码 图形验证码 ... 这些应用 ...

  9. Cordova - IOS浏览器里面数字被当做电话号码

    网页上有连续超过5个数字,ios浏览器就会当做手机号码,如果某行文字有颜色,那么这个连续的数字就没颜色,变黑色了. 解决方法:在html页面头部加入下面代码 <meta name="f ...

  10. HTML中META标签的使用

    一.META标签简介 <meta> 元素可提供有关页面的元信息,元数据总是以名称/值的形式被成对传递的. <meta> 标签位于文档的头部,不包含任何内容. <meta& ...