bzoj2208 [Jsoi2010]连通数(scc+bitset)
2015-12-18 15:28
696 查看
2208: [Jsoi2010]连通数
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1879 Solved: 778
[Submit][Status][Discuss]
Description
Input
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。Output
输出一行一个整数,表示该图的连通数。Sample Input
3010
001
100
Sample Output
9HINT
对于100%的数据,N不超过2000。Source
第一轮【思路】
强连通分量+bitset传递闭包。
求出scc,缩点。对于新的DAG,如果两个scc之间相连则ans+=sccsz[i]*sccsz[j]。利用bitset与递推判断相连。
【代码】
#include<cstdio> #include<bitset> #include<queue> #include<stack> #include<vector> #include<cstring> #include<iostream> using namespace std; const int maxn = 2000+10; int pre[maxn],lowlink[maxn],sccno[maxn],sccsz[maxn],dfs_clock,scc_cnt; vector<int> G[maxn]; stack<int> S; int dfs(int u) { pre[u]=lowlink[u]=++dfs_clock; S.push(u); for(int i=0;i<G[u].size();i++) { int v=G[u][i]; if(!pre[v]) { dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if(!sccno[v]) { lowlink[u]=min(lowlink[u],pre[v]); } } if(lowlink[u]==pre[u]) { scc_cnt++; for(;;) { int x=S.top(); S.pop(); sccno[x]=scc_cnt; sccsz[scc_cnt]++; if(x==u) break; } } } void find_scc(int n) { memset(pre,0,sizeof(pre)); memset(sccsz,0,sizeof(sccsz)); memset(sccno,0,sizeof(sccno)); scc_cnt=dfs_clock=0; for(int i=0;i<n;i++) if(!pre[i]) dfs(i); } bitset<maxn> f[maxn]; //使用bitset int n,in[maxn]; char s[maxn]; vector<int> Gx[maxn]; void rebuild() { for(int i=1;i<=scc_cnt;i++) in[i]=0; for(int i=0;i<n;i++) { int u=sccno[i]; for(int j=0;j<G[i].size();j++) { int v=sccno[G[i][j]]; if(u!=v) Gx[u].push_back(v),in[v]++; } } } queue<int> q; void solve() { for(int i=1;i<=scc_cnt;i++) f[i][i]=1; for(int i=1;i<=scc_cnt;i++) if(!in[i]) q.push(i); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=0;i<Gx[u].size();i++) { int v=Gx[u][i]; f[v]|=f[u]; //传递闭包 if((--in[v])==0) q.push(v); } } } int main() { scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%s",s); for(int j=0;j<n;j++) { if(s[j]-'0') G[i].push_back(j); } } find_scc(n); rebuild(); solve(); int ans=0; for(int i=1;i<=scc_cnt;i++) { for(int j=1;j<=scc_cnt;j++) if(f[i][j]) ans+=sccsz[i]*sccsz[j]; } printf("%d\n",ans); return 0; }
相关文章推荐
- Python+Selenium+PhantomJS下载JavaScript异步加载网页
- 使用Jsoup实现简单的页面信息爬取
- 条码解析的一片js
- json格式转换
- Ext.js5的小鲱鱼分页(11)(silding pager)
- document.write插入js标签会覆盖页面的问题
- GOF提出的23种设计模式是哪些 设计模式有创建形、行为形、结构形三种类别 常用的Javascript中常用设计模式的其中17种 详解设计模式六大原则
- JSON的一些使用
- js 解析json
- json小例子
- javascript DOM编程艺术(笔记)
- jsp页面校验数字 正则表达式
- json2.js的作用与使用示例
- js获取url传值的方法
- js验证input不为空且两次输入密码相同
- Ext.js5的带分页的表格(10)
- Servlet/JSP随笔录
- 利用VBA将excel数据表生成JSON文件(utf8)
- 计时器 setInterval clearInterval setTimeout
- jsp页面出现两个相同id的标签的读取顺序