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
原创粉丝点击