BZOJ 2206 缩圈+拓扑[tarjan模板]
来源:互联网 发布:小米3可以用4g网络吗 编辑:程序博客网 时间:2024/05/19 13:45
时间:3000ms左右的代码(并查集维护,邻接矩阵暴力跑重建的边)
update:把并查集处理后跑祖先间的边,换为重建图,效率或许可以提高.(已确认,可以优化到850ms左右,代码附在后面)
#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <bitset>#define maxn 3002#define maxm 8000020using namespace std;inline void read(int &x) { char ch; bool flag = false; for (ch = getchar(); !isdigit(ch); ch = getchar())if (ch == '-') flag = true; for (x = 0; isdigit(ch); x = x * 10 + ch - '0', ch = getchar()); x = flag ? -x : x;}inline void write(int x) { static const int maxlen = 100; static char s[maxlen]; if (x < 0) { putchar('-'); x = -x;} if (!x) { putchar('0'); return; } int len = 0; for (; x; x /= 10) s[len++] = x % 10 + '0'; for (int i = len - 1; i >= 0; --i) putchar(s[i]);}int n;int pre[maxm],now[maxn],son[maxm],tot;int dfn[maxn],low[maxn],cnt;int fa[maxn];int d[maxn],top;bool IN[maxn];int size[maxn];bitset<maxn> g[maxn];int sum[maxn];void build(int a,int b){pre[++tot]=now[a];now[a]=tot;son[tot]=b;}int get(int x){if (x!=fa[x]) return fa[x]=get(fa[x]);return x;}void dfs(int x){dfn[x]=low[x]=++cnt; d[++top]=x;IN[x]=1;for (int p=now[x];p;p=pre[p]) if (dfn[ son[p] ]==0) { dfs(son[p]); low[x]=min(low[x],low[son[p]]); } else if (IN[son[p]]) low[x]=min(low[x],dfn[son[p]]);if (low[x]==dfn[x]) { while ( d[top]!= x ) { fa[ get ( d[top] ) ] =get(x); IN[ d[top] ]=0; --top; } --top; IN[x]=0; }}char s[maxn];bool bo[maxn][maxn];bool vis[maxn];void doit(int x){for (int i=1;i<=n;i++) if (fa[i]==i) if (g[x][i]) if(!vis[i]) { doit(i); g[x]|=g[i]; } else g[x]|=g[i];vis[x]=1;}int main(){ read(n); for (int i=1;i<=n;i++) { scanf("%s",s); int len=strlen(s); for (int j=0;j<len;j++) if (s[j]=='1') build(i,j+1); } for (int i=1;i<=n;i++) fa[i]=i; for (int i=1;i<=n;i++) if (dfn[i]==0) dfs(i); for (int i=1;i<=n;i++) for (int p=now[i];p;p=pre[p]) if (get(son[p])!=get(i)) g[get(i)][get( son[p] )]=1; for (int i=1;i<=n;i++) if (fa[i]==i) doit(i); for (int i=1;i<=n;i++) size[ get(i) ]++; int ans=0; for (int i=1;i<=n;i++) if (fa[i]==i) { int sum=size[i]; for (int j=1;j<=n;j++) if (fa[j]==j) if (g[i][j]) sum+=size[j]; ans+=sum*size[i]; } printf("%d\n",ans); return 0;}
时间:850ms左右 (染色后重建图,降低点和边的数量)
#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>#include <bitset>#define maxn 3002#define maxm 4000020using namespace std;inline void read(int &x) { char ch; bool flag = false; for (ch = getchar(); !isdigit(ch); ch = getchar())if (ch == '-') flag = true; for (x = 0; isdigit(ch); x = x * 10 + ch - '0', ch = getchar()); x = flag ? -x : x;}inline void write(int x) { static const int maxlen = 100; static char s[maxlen]; if (x < 0) { putchar('-'); x = -x;} if (!x) { putchar('0'); return; } int len = 0; for (; x; x /= 10) s[len++] = x % 10 + '0'; for (int i = len - 1; i >= 0; --i) putchar(s[i]);}int n;int pre[maxm],now[maxn],son[maxm],tot;int _pre[maxm],_now[maxn],_son[maxm],_tot;int dfn[maxn],low[maxn],cnt;int d[maxn],top;bool IN[maxn];int size[maxn],color[maxn],color_tot;bitset<maxn> g[maxn];void build(int a,int b){pre[++tot]=now[a];now[a]=tot;son[tot]=b;}void _build(int a,int b){_pre[++_tot]=_now[a];_now[a]=_tot;_son[_tot]=b;}void dfs(int x){dfn[x]=low[x]=++cnt; d[++top]=x;IN[x]=1;for (int p=now[x];p;p=pre[p]) if (dfn[ son[p] ]==0) { dfs(son[p]); low[x]=min(low[x],low[son[p]]); } else if (IN[son[p]]) low[x]=min(low[x],dfn[son[p]]);if (low[x]==dfn[x]) { ++color_tot; while ( d[top]!= x ) { color[ d[top] ]=color_tot; IN[ d[top] ]=0; --top; } --top; IN[x]=0; color[x]=color_tot; }}void rebuild(){ for (int i=1;i<=n;i++) for (int p=now[i];p;p=pre[p]) if ( color[ son[p] ] !=color[ i ] ) if (!g[ color[i] ] [ color[son[p]] ]) { g[ color[i] ] [ color[son[p]] ] = 1; _build(color[i],color[son[p] ]); }}char s[maxn];bool bo[maxn][maxn];bool vis[maxn];void doit(int x){ for (int p= _now[x] ;p;p= _pre [p]) if (!vis[ _son[p] ]) { doit( _son[p] ); g[x]|=g[ _son[p] ]; } else g[x]|=g[ _son[p] ];vis[x]=1;}int main(){ read(n); for (int i=1;i<=n;i++) { scanf("%s",s); int len=strlen(s); for (int j=0;j<len;j++) if (s[j]=='1') build(i,j+1); } for (int i=1;i<=n;i++) if (dfn[i]==0) dfs(i); for (int i=1;i<=n;i++) size[ color[i] ]++; rebuild(); for (int i=1;i<=color_tot;i++) if (!vis[i]) doit(i); int ans=0; for (int i=1;i<=color_tot;i++) { int sum=size[i]; for (int j=1;j<=color_tot;j++) if (g[i][j]) sum+=size[j]; ans+=sum*size[i]; } printf("%d\n",ans); return 0;}
阅读全文
0 0
- BZOJ 2206 缩圈+拓扑[tarjan模板]
- bzoj 3887 tarjan+拓扑排序
- [BZOJ 1093 && YZOI1172] Tarjan缩点+拓扑DP 最大半连通子图
- BZOJ 1924 [Sdoi2010]所驼门王的宝藏 tarjan缩点+拓扑DP
- BZOJ 1512 [POI2006]Pro-Professor Szu Tarjan缩点+拓扑DP
- bzoj 2707: [SDOI2012]走迷宫 (高斯消元+概率期望+tarjan缩点+拓扑序)
- BZOJ 1093 浅谈tarjan缩点DAG最长路径即拓扑排序
- BZOJ 1093 最大半连通子图(tarjan缩点 拓扑排序)
- [BZOJ]1093: [ZJOI2007]最大半连通子图 Tarjan缩点+拓扑图DP
- BZOJ 2140 浅谈 Tarjan 算法及模板
- BZOJ 2208 JSOI2010 连通数 Tarjan+拓扑排序
- BZOJ 3887 Usaco2015 Jan Grass Cownoisseur Tarjan+拓扑排序
- BZOJ[3887][Usaco2015 Jan]Grass Cownoisseur Tarjan+拓扑排序
- Tarjan缩点模板
- poj 2762 tarjan+缩点+拓扑排序
- UOJGraph(tarjan缩点+拓扑)
- 洛谷p3387 拓扑+tarjan缩点
- Tarjan模板
- 白话经典算法系列之三 希尔排序的实现
- LA 4270 离散平方根
- C语言结构体对象间直接赋值
- tomcat启动报错ClassNotFoundExceptiion:org.springframework.web.context.ContextLoaderListener
- Android 命名规范 (提高代码可以读性)
- BZOJ 2206 缩圈+拓扑[tarjan模板]
- 数学 | 推理 | 思维 | 打表 | 找规律 | 贪心 | 暴力
- CC2640R2F BLE5.0 蓝牙协议栈信道选择算法#2(CSA#2)
- canvas实现一颗树的生长到开花
- td百分比显示内容过多以点号(...)显示
- 生产环境部署Hadoop+Spark+HBase+Hue
- [ RESP-API ] SwaggerUI+SpringMVC——构建RestFulAPI的可视化界面
- 【tomcat】Tomcat以debug模式启动
- Angular管道设置 :