zoukankan      html  css  js  c++  java
  • BZOJ2208:[JSOI2010]连通数——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=2208

     floyd压位是神马东西……

     我们tarjan缩点之后反向拓扑就可以记录联通块可达状态,然后可达就sz[i]*sz[j]就行了。

    #include<map>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cctype>
    #include<bitset>
    #include<vector>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=2005;
    struct edge{
        int cnt,head[N];
        int to[N*N],nxt[N*N];
        edge(){
            cnt=0;memset(head,0,sizeof(head));
        }
        inline void add(int u,int v){
            to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;
        }
    }e,f;
    char s[N];
    int sz[N],dfn[N],low[N],to[N],t,l;
    bool inq[N];
    stack<int>q;
    void tarjan(int u){
        dfn[u]=low[u]=++t;
        q.push(u);inq[u]=1;
        for(int i=e.head[u];i;i=e.nxt[i]){
            int v=e.to[i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }else if(inq[v]){
                low[u]=min(low[u],dfn[v]);
            }
        }
        if(dfn[u]==low[u]){
            int v;l++;
            do{
                v=q.top();q.pop();inq[v]=0;
                to[v]=l;sz[l]++;
            }while(v!=u);
        }
    }
    int deg[N];
    queue<int>que;
    bitset<N>d[N];
    void topu(int n){
        for(int i=1;i<=l;i++){
            d[i][i]=1;
            if(!deg[i])que.push(i);
        }
        while(!que.empty()){
            int u=que.front();que.pop();
            for(int i=f.head[u],v;i;i=f.nxt[i]){
                deg[v=f.to[i]]--;
                d[v]|=d[u];
                if(!deg[v])que.push(v);
            }
        }
    }
    int main(){
        int n;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')e.add(i,j);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])tarjan(i);
        for(int u=1;u<=n;u++){
            for(int i=e.head[u];i;i=e.nxt[i]){
                int v=e.to[i];
                if(to[u]==to[v])continue;
                bool flag=1;
                for(int j=f.head[to[v]];j&&flag;j=f.nxt[j])
                    if(f.to[j]==to[u])flag=0;
                if(flag)f.add(to[v],to[u]),deg[to[u]]++;
            }
        }
        topu(l);
        int ans=0;
        for(int i=1;i<=l;i++)
            for(int j=1;j<=l;j++)
                if(d[i][j])ans+=sz[i]*sz[j];
        printf("%d
    ",ans);
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

    +本文作者:luyouqi233。               +

    +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    视差插件parallarx
    经典幻灯片插件Swiper
    经典全屏滚动插件fullPage.js
    Dialog插件artDialog
    html5 canvas 做的一个时钟效果
    CSS3 Transitions, Transforms和Animation使用简介与应用展示
    微软官方下载地址
    Windows 7 下配置IIS,并且局域网内可访问(转载)
    C# 使用HttpWebRequest 实现文件的上传
    小图标网站
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/9210693.html
Copyright © 2011-2022 走看看