zoukankan      html  css  js  c++  java
  • 【BZOJ2208】连通数(JSOI2010)-SCC+DP+bitset

    测试地址:连通数
    做法:本题需要用到SCC+DP+bitset。
    看到和有向图的连通性有关就想到用SCC缩点,对于缩出来的DAG,一个直观的想法就是DP,大多数同学应该会马上想到这样的状态定义:令f(i)为能到达点i的点的数目,然后blablabla……
    很遗憾,这个状态定义是错的,而且非常明显是错的,因为如果有两个不同的点能到达当前点,而又有一个相同的点能到达这两个点,很明显上面的方法就不能处理这样的问题。
    为了处理重复的问题,想到一种暴力,令f(i)为能到达点i的点的集合,然后按拓扑序DP。但是如果直接用布尔数组来存储,空间和时间复杂度都会爆炸,因此我们选用一个非常有用的STL——bitset来维护这样的集合。
    bitset通过内置的方法来优化各种位运算的时间复杂度和空间复杂度(你可以理解为类似压位但比压位更加高端的一些东西),具体的用法可以参看这篇大佬的博客:点我,那么我们就可以轻易地解决这一题了,时间复杂度大概是O(nm64)
    (不过听说这题数据太水,暴力O(nm)都能水过……)
    下面这篇代码在洛谷AC,在BZOJ莫名RE,求大佬指点原因。
    以下是本人代码:

    #include <bits/stdc++.h>
    using namespace std;
    int n,first[4010]={0},tot=0;
    int st[2010],dfn[2010],low[2010],tim=0,top=0,totscc,belong[2010];
    int h,t,q[4010],in[4010]={0},siz[4010];
    char s[2010];
    bool vis[2010]={0},inst[2010]={0};
    struct edge
    {
        int v,next;
    }e[2000010];
    bitset<2010> f[4010];
    
    void insert(int a,int b)
    {
        e[++tot].v=b;
        e[tot].next=first[a];
        first[a]=tot;
    }
    
    void init()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",s+1);
            for(int j=1;j<=n;j++)
                if (s[j]-'0') insert(i,j);
        }
        totscc=n;
    }
    
    void tarjan(int v)
    {
        vis[v]=inst[v]=1;
        st[++top]=v;
        dfn[v]=low[v]=++tim;
        int now=top;
        for(int i=first[v];i;i=e[i].next)
        {
            if (!vis[e[i].v])
            {
                tarjan(e[i].v);
                low[v]=min(low[v],low[e[i].v]);
            }
            else if (inst[e[i].v]) low[v]=min(low[v],dfn[e[i].v]);
        }
        if (low[v]==dfn[v])
        {
            totscc++;
            siz[totscc]=top-now+1;
            for(int i=now;i<=top;i++)
            {
                belong[st[i]]=totscc;
                inst[st[i]]=0;
            }
            top=now-1;
        }
    }
    
    void compress()
    {
        for(int i=1;i<=n;i++)
            for(int j=first[i];j;j=e[j].next)
                if (belong[i]!=belong[e[j].v])
                {
                    insert(belong[i],belong[e[j].v]);
                    in[belong[e[j].v]]++;
                }
    }
    
    void dp()
    {
        h=1,t=0;
        for(int i=n+1;i<=totscc;i++)
            if (!in[i]) q[++t]=i;
        while(h<=t)
        {
            int v=q[h++];
            f[v].set(v);
            for(int i=first[v];i;i=e[i].next)
            {
                f[e[i].v]|=f[v];
                in[e[i].v]--;
                if (!in[e[i].v]) q[++t]=e[i].v;
            }
        }
        int cnt=0;
        for(int i=n+1;i<=totscc;i++)
            for(int j=n+1;j<=totscc;j++)
                cnt+=(f[i].test(j))*siz[i]*siz[j];
        printf("%d",cnt);
    }
    
    int main()
    {
        init();
        for(int i=1;i<=n;i++)
            if (!vis[i]) tarjan(i);
        compress();
        dp();
    
        return 0;
    }
  • 相关阅读:
    互联网博物馆
    CSS简介和CSS选择器
    perl 面向对象 use base
    mysql tcp 4层负载
    mysql tcp 4层负载
    mysql Emoji表情字符集转换
    mysql Emoji表情字符集转换
    html submit 登录
    html submit 登录
    haroxy hdr
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793388.html
Copyright © 2011-2022 走看看