[BZOJ 2208] 连通数

Link:

BZOJ 2208 连通数

Solution:

传递闭包模板题

传递闭包是集合中最小的二元关系,其实就是对二元关系的不断拓展,一般用$floyd$求解

这里要先跑一遍$tarjan$求出$SCC$,然后在$TopoSort$时顺便传递闭包,最后统计答案即可

 

Tips:

1、在$DAG$上递推使用拓扑排序更高效,直接$dfs$时间复杂度没有保证,很可能$TLE$

2、如需对二进制位统一处理(位运算),使用$bitset$,能通过压位快32倍

3、这题$O(n*m)$和$O(\frac{n^3}{32})$的纯暴力都能过……

 

Code:

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int MAXN=2005;
ll res=0;
bool vis[MAXN],instack[MAXN];
vector<int> G[MAXN];char dat[MAXN][MAXN];
int n,in[MAXN],low[MAXN],dfn[MAXN],col[MAXN],sum[MAXN],tp=0,cnt=0;

stack<int> s;
bitset<MAXN> f[MAXN];

void tarjan(int x)
{
    dfn[x]=low[x]=++tp;
    vis[x]=instack[x]=true;
    s.push(x);
    
    for(int i=0;i<G[x].size();i++)
    {
        int v=G[x][i];
        if(instack[v])
            low[x]=min(low[x],low[v]);
        else if(!vis[v])
            tarjan(v),low[x]=min(low[x],low[v]);
    }
    
    if(low[x]==dfn[x])
    {
        int tmp=-1;cnt++;
        while(tmp!=x)
        {
            tmp=s.top();s.pop();
            instack[tmp]=false;
            col[tmp]=cnt;sum[cnt]++;
        }
    }
}

void Topo_sort()
{
    for(int i=1;i<=cnt;i++) f[i][i]=1;
    queue<int> q;
    for(int i=1;i<=cnt;i++) if(!in[i]) q.push(i);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i];f[v]|=f[u];
            if(!(--in[v])) q.push(v);
        }
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%s",dat[i]+1);
        for(int j=1;j<=n;j++)
            if(dat[i][j]=='1') G[i].push_back(j);
    }
    
    for(int i=1;i<=n;i++)
        if(!vis[i]) tarjan(i);
    
    for(int i=0;i<MAXN;i++) G[i].clear();
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)    
            if(dat[i][j]=='1' && col[i]!=col[j])    
                G[col[j]].push_back(col[i]),in[col[i]]++;
    
    Topo_sort();
    for(int i=1;i<=cnt;i++)
        for(int j=1;j<=cnt;j++)
            if(f[i][j]) res+=1ll*sum[i]*sum[j];
    
    printf("%lld",res);
    return 0;
}

 

posted @ 2018-06-30 21:33  NewErA  阅读(330)  评论(0编辑  收藏  举报