BZOJ.2208.[JSOI2010]连通数(bitset Tarjan 拓扑)
先缩点,对于scc之间贡献即为szscc[i]*szscc[j]
用f[i][j]表示scci是否能到sccj
拓扑排序,每次把now的f或上to的f
用bitset优化
//63888kb 1080ms
#include <cstdio>
#include <cctype>
#include <bitset>
#include <algorithm>
#define gc() getchar()
const int N=2005,M=4e6+5;
int n,bel[N],Enum,H[N],Snum,Sh[N];
int cnt,dgr[N],sz[N],dfn[N],low[N],id,sk[N],top,q[N];
bool ins[N];
char s[N];
std::bitset<N> f[N];
struct Edge
{
int nxt,to;
}e[M],se[M];
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
inline void AddEdge(int u,int v){
e[++Enum].to=v, e[Enum].nxt=H[u], H[u]=Enum;
}
inline void AddEdge2(int u,int v){
++dgr[v];
se[++Snum].to=v, se[Snum].nxt=Sh[u], Sh[u]=Snum;
}
void Tarjan(int x)
{
dfn[x]=low[x]=++id, sk[++top]=x, ins[x]=1;
for(int v,i=H[x]; i; i=e[i].nxt)
if(!dfn[v=e[i].to])
Tarjan(v), low[x]=std::min(low[x],low[v]);
else if(ins[v])
low[x]=std::min(low[x],dfn[v]);
if(dfn[x]==low[x])
{
++cnt;
do{
bel[sk[top]]=cnt, ++sz[cnt];
ins[sk[top--]]=0;
}while(x!=sk[top+1]);
}
}
void Rebuild()
{
for(int x=1; x<=n; ++x)
for(int i=H[x]; i; i=e[i].nxt)
if(bel[e[i].to]!=bel[x]) AddEdge2(bel[e[i].to],bel[x]);//反向
}
int Solve()//cnt与n别混
{
int h=0,t=0;
for(int i=1; i<=cnt; ++i)
if(!dgr[i]) q[t++]=i;
for(int i=1; i<=cnt; ++i) f[i][i]=1;
while(h<t)
{
int x=q[h++];
for(int i=Sh[x]; i; i=se[i].nxt)
{
if(!--dgr[se[i].to]) q[t++]=se[i].to;
f[se[i].to]|=f[x];
}
}
int res=0;
for(int i=1; i<=cnt; ++i)
for(int j=1; j<=cnt; ++j)
if(f[i][j]) res+=sz[i]*sz[j];
return res;
}
int main()
{
n=read();
for(int i=1; i<=n; ++i)
{
scanf("%s",s+1);
for(int j=1; j<=n; ++j)
if(s[j]=='1') AddEdge(i,j);
}
for(int i=1; i<=n; ++i)
if(!dfn[i]) Tarjan(i);
Rebuild();
printf("%d",Solve());
return 0;
}
BZOJ.2208.[JSOI2010]连通数(bitset Tarjan 拓扑)的更多相关文章
- bzoj 2208: [Jsoi2010]连通数【tarjan+拓扑+dp】
我总觉得枚举点bfs也行-- tarjan缩点,记一下每个scc的size,bitset压一下scc里的点,然后按拓扑倒序向上合并到达状态,然后加ans的时候记得乘size #include<i ...
- BZOJ 2208: [Jsoi2010]连通数 tarjan bitset
2208: [Jsoi2010]连通数 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- bzoj 2208 [Jsoi2010]连通数
2208: [Jsoi2010]连通数 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 输入数据第一行是图顶点的数量,一个正整数N ...
- BZOJ 2208: [Jsoi2010]连通数( DFS )
n只有2000,直接DFS就可以过了... -------------------------------------------------------------------------- #in ...
- BZOJ 2208 JSOI2010 连通数 Tarjan+拓扑排序
题目大意:给定一个n个点的有向图,求有多少点对(x,y),使x沿边可到达y 设f[i][j]为从i到j是否可达 首先强联通分量中的随意两个点均可达 于是我们利用Tarjan缩点 缩点之后是一个拓扑图. ...
- 2208: [Jsoi2010]连通数
2208: [Jsoi2010]连通数 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1371 Solved: 557[Submit][Status ...
- 【BZOJ2208】[JSOI2010]连通数(Tarjan)
[BZOJ2208][JSOI2010]连通数(Tarjan) 题面 BZOJ 洛谷 题解 先吐槽辣鸡洛谷数据,我写了个\(O(nm)\)的都过了. #include<iostream> ...
- 2208: [Jsoi2010]连通数 - BZOJ
Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. Output 输出一行一个整数,表示该图 ...
- 【BZOJ】2208 [Jsoi2010]连通数
[题意]给定n个点的有向图,求可达点对数(互相可达算两对,含自身).n<=2000. [算法]强连通分量(tarjan)+拓扑排序+状态压缩(bitset) [题解]这题可以说非常经典了. 1. ...
随机推荐
- 【转】Shell编程基础篇-下
[转]Shell编程基础篇-下 1.1 条件表达式 1.1.1 文件判断 常用文件测试操作符 常用文件测试操作符 说明 -d文件,d的全拼为directory 文件存在且为目录则为真,即测试表达式成立 ...
- (DT系列五)Linux kernel 是怎么将 devicetree中的内容生成plateform_device【转】
转自:https://blog.csdn.net/lichengtongxiazai/article/details/38942033 Linux kernel 是怎么将 devicetree中的内容 ...
- Linux系统调用的运行过程【转】
本文转自:http://blog.csdn.net/kernel_learner/article/details/7331505 在Linux中,系统调用是用户空间访问内核的唯一手段,它们是内核唯一的 ...
- python中的这些坑,早看早避免。
python中的这些坑,早看早避免. 说一说python中遇到的坑,躲坑看这一篇就够了 传递参数时候不要使用列表 def foo(num,age=[]): age.append(num) print( ...
- 【转】C语言正确使用extern关键字
利用关键字extern,可以在一个文件中引用另一个文件中定义的变量或者函数,下面就结合具体的实例,分类说明一下. 一.引用同一个文件中的变量 #include<stdio.h> int f ...
- 转载:JAVA序列化与反序列化 (作者:YSOcean)
原文:https://www.cnblogs.com/ysocean/p/6870069.html File 类的介绍:http://www.cnblogs.com/ysocean/p/6851878 ...
- oracle 各个版本下载地址
Oracle9i Database Release 2 Enterprise/Standard/Personal Edition for Windows NT/2000/XP http://downl ...
- hdu2289二分答案 圆台体积
精度小一点就能过 #include<bits/stdc++.h> #define maxn 1000000009 #define esp 1e-9 #define PI 3.1415926 ...
- hdu3183 rmq求区间最值的下标
两个月前做的题,以后可以看看,是rmq关于求区间最值的下标 /* hdu3183 终点 给一个整数,可以删除m位,留下的数字形成一个新的整数 rmq 取n-m个数,使形成的数最小 */ #includ ...
- cf1061D 贪心+multiset 好题!
cf上的思维题真好! 本题是在模拟的基础上贪心即可:将n段时间按照左端点(右端点为第二关键字)从小到大排序,然后遍历每一个时间段. 对于每一个时间段[li,ri],先找到multiset中最靠近li但 ...