题目传送门


题目描述

度量一个有向图连通情况的一个指标是连通数,指图中可达顶点对的个数。

在上图中,顶点1可以到达1、2、3、4、5。

顶点2可以到达2、3、4、5。

顶点3可以到达3、4、5。

顶点4、5均只能到达自身,所以它的连通数为14。

请编写一个程序,输入一个图,求它的连通数。


输入格式

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


输出格式

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


样例

样例输入:

3
010
001
100

样例输出:

9


数据范围与提示

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


题解

千万不要以为这道题数据范围N≤2000就可以暴力,N≤2000意味着最多会有$N^{2}$条边,dfs一遍遍历时间复杂度为边数,那么这道题就会被卡成$N^{3}$。

不过由于数据比较水,暴力卡常也可以A掉……

然而,占用评测资源显然是一种rp--的行为,所以考虑优化。

bitset!!!

利用floyed的思想。

空间和时间都在很大程度上得到了优化。

还不够快?

考虑塔尖缩点,一个强联通分量缩成一个点之后只要经过这个点,它里面的点都能被经过,所以记录size即可。

好吧,典型的空间换时间……


代码时刻

暴力:

#include<bits/stdc++.h>
using namespace std;
struct rec
{int nxt;int to;
}e[4000000];
int head[2001],cnt;
bool vis[2001];
long long ans;
char ch[2001];
void add(register int x,register int y)
{e[++cnt].nxt=head[x];e[cnt].to=y;head[x]=cnt;
}
void dfs(register int x)
{vis[x]=1;ans++;for(register int i=head[x];i;i=e[i].nxt)if(!vis[e[i].to])dfs(e[i].to);
}
int main()
{int n;scanf("%d",&n);for(register int i=1;i<=n;i++){scanf("%s",ch+1);for(register int j=1;j<=n;j++)if(ch[j]=='1')add(i,j);}for(register int i=1;i<=n;i++)memset(vis,0,sizeof(vis)),dfs(i);printf("%d",ans);return 0;
}
//推荐使用register进行卡常,评测机稍卡都有可能过不了,然而我5分钟1A了……

bitset优化:

#include<bits/stdc++.h>
using namespace std;
char ch[2001];
bitset<2001> a[2001];//bitset
int ans;
int main()
{int n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",ch+1);for(int j=1;j<=n;j++)if(ch[j]=='1')a[i][j]=1;a[i][i]=1;}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(a[j][i])a[j]|=a[i];//运用floyed思想for(int i=1;i<=n;i++)ans+=a[i].count();//统计答案cout<<ans<<endl;return 0;
}
//我觉得代码好小巧,你觉得呢?

塔尖+bitset:

#include<bits/stdc++.h>
using namespace std;
struct rec
{int nxt;int to;
}e[4000000],wzc[4000000];
int n;
int head[2001],cnt;
int headw[2001],cntw;
long long ans;
char ch[2001];
int dfn[2001],low[2001],sta[2001],ins[2001],c[2001],size[2001],num,top,tot;
int que[2001],d[2001],lft=1,rht=1;
bitset<2001> a[2001];
void add(int x,int y)//旧图
{e[++cnt].nxt=head[x];e[cnt].to=y;head[x]=cnt;
}
void add_w(int x,int y)//新图
{wzc[++cntw].nxt=headw[x];wzc[cntw].to=y;headw[x]=cntw;
}
void tarjan(int x)//缩点
{dfn[x]=low[x]=++num;sta[++top]=x;ins[x]=1;for(int i=head[x];i;i=e[i].nxt){if(!dfn[e[i].to]){tarjan(e[i].to);low[x]=min(low[x],low[e[i].to]);}else if(ins[e[i].to])low[x]=min(low[x],dfn[e[i].to]);}if(dfn[x]==low[x]){tot++;int y;do{y=sta[top--];ins[y]=0;c[y]=tot;size[tot]++;}while(x!=y);}
}
void build()//建新图
{for(int x=1;x<=n;x++)for(int i=head[x];i;i=e[i].nxt)if(c[x]!=c[e[i].to]){add_w(c[x],c[e[i].to]);d[c[e[i].to]]++;}
}
void _doudou()//统计答案
{for(int i=1;i<=tot;i++)if(!d[i])que[++rht]=i;while(lft<=rht){a[que[lft]][que[lft]]=1;for(int i=headw[que[lft]];i;i=wzc[i].nxt){a[wzc[i].to]|=a[que[lft]];d[wzc[i].to]--;if(!d[wzc[i].to])que[++rht]=wzc[i].to;}lft++;}for(int i=1;i<=tot;i++)for(int j=1;j<=tot;j++)if(a[i][j])ans+=size[i]*size[j];
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%s",ch+1);for(int j=1;j<=n;j++)if(ch[j]=='1')add(i,j);}for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);build();_doudou();printf("%d",ans);return 0;
}
//比较恶心,考试的时候建议使用前两种做法,这种做法仅供参考和装逼……


rp++

转载于:https://www.cnblogs.com/wzc521/p/11187525.html

[BZOJ2208]:[Jsoi2010]连通数(暴力 or bitset or 塔尖?)相关推荐

  1. 2208: [Jsoi2010]连通数(Trajan+bitset)

    2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 2929  Solved: 1280 [Submit][Sta ...

  2. bzoj2208 [Jsoi2010]连通数 强连通分量缩点+拓扑排序+bitset

    Description 对于100%的数据,N不超过2000. Solution 容易想到要tarjan缩点按拓扑序递推,但是去重的步骤不好弄 C++STL中有bitset,用这个当成二进制按位状压即 ...

  3. BZOJ2208 [Jsoi2010]连通数

    题目描述: 度量一个有向图连通情况的一个指标是连通,指途中可达点对的个数. 下图的连通数是14 现在要你求出连通数 n<=2000 题解: 网上的题解有的写得很复杂,但是看到n的范围这么小,当然 ...

  4. [bzoj2208][Jsoi2010]连通数

    一道传递闭包裸题.tarjan+拓扑dp也很强而且貌似更快.本来想写的. 然而查题解的时候发现一个博主的一句话引起了我的共鸣. bzoj上这道题rank前面都是1500B+的大佬,很快,几百ms,到了 ...

  5. bzoj2208 [Jsoi2010]连通数

    题目链接 先是强连通分量缩点,然后出来一个DAG 然后就可以DP啦,要找出每个SCC能到达的SCC有哪些 如果直接存一个二维数组来传递闭包的话肯定会TLE对吧 于是我们使用了神奇的bitset就快多了 ...

  6. bzoj2208: [Jsoi2010]连通数

    补写. 学了学用bitset优化floyd,做这题比用强联通缩点+DP方便多了. bitset具体就是一串编码,比如说定义bitset<2100>b,b就是一个2100位的01串. 由于位 ...

  7. bzoj2208:[Jsoi2010]连通数

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

  8. 2208: [Jsoi2010]连通数

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

  9. BZOJ 2208[Jsoi2010]连通数

    题面: 2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 3100  Solved: 1347 [Submit] ...

最新文章

  1. 985博士:导师是院士,直到毕业,我们都没单独说过一句话
  2. L2:grep使用正则表达式
  3. Shell命令-关机重启及注销之logout、exit
  4. Lodash 中文文档 (v3.10.1) - “Lang” 方法
  5. Python基础知识(第二天)
  6. 如何设计一门语言(九)——类型
  7. 【读书笔记】练习的心态
  8. 随时更新———个人喜欢的关于模式识别、机器学习、推荐系统、图像特征、深度学习、数值计算、目标跟踪等方面个人主页及博客
  9. Win10+Torch1.9+CUDA11.1成功配置YOLOX预测环境
  10. SpringCloud微服务架构学习(二)常见的微服务架构
  11. 09.显式的实现接口的方法
  12. Python 告诉你:8.3 分口碑炸裂!潘粤明版《鬼吹灯》到底好看在哪儿?
  13. 【渝粤教育】国家开放大学2018年秋季 1131t卫生经济学 参考试题
  14. Illustrator中文版教程,如何在AI中以不同的方式组合形状?
  15. mysql java 日期_Mysql和JAVA中的几个日期操作
  16. Linux(ubuntu18.04)安装eclipse教程
  17. ArcGIS导出地图是全黑的
  18. 二叉树的五种遍历方式
  19. 学软件测试最好的几本书,这8本书能帮你很多
  20. java中虚数咋表示,虚数的定义(高中虚数i的运算公式举例)

热门文章

  1. Linux|centos7|终端录屏神器asciinema的部署和初步使用
  2. css display: grid属性repeat
  3. 仿金拱门的外卖微信小程序
  4. 用python写生日快乐说说_祝自己生日快乐说说
  5. 电脑监控软件哪个好?都有什么功能?
  6. 中学教学参考期刊点评_版面费_审稿
  7. HLA-Face: Joint High-Low Adaptation for Low Light Face Detection
  8. 3.4nbsp;企业家——3.4.1nbsp;史蒂…
  9. 不乱于心,不困于情。不畏将来,不念过往
  10. 新手站长做网站的一些技巧