zoukankan      html  css  js  c++  java
  • BZOJ2208连通数

    还是挺简单的tarjan。

    判断时可能重复,直接bitset搞定。

    首先tarjan缩点,每个scc的内部肯定能互相到达,更一下,而且一个scc里的各个点的贡献肯定是一样的,topsort,更新答案就可以了,用bitset的count成上scc大小即可。

    据说数据很水,大约O(n^3)可过,但是我看了看,没缩点,直接dfs,细节比较多,略烦,上述算法比较长,但是脑量比较小。还是比较好的,tarjan和topsort打得熟就15min搞定。

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<stack>
    #include<bitset>
    #include<map>
    using namespace std;
    struct EDGE{
        int ed,nex;
    }edge[4000050],edgec[4000050];
    int num,numc,ans,first[3000],firstc[3000];
    int n,ord,sccnum,top;
    int sta[1000000],dfn[3000],low[3000],bl[3000],du[3000];
    char ch[3000];
    bool ins[3000];
    vector<int>scc[3000];
    bitset<3000>s[3000];
    void add(int st,int ed){
    //    cout<<"st="<<st<<" ed="<<ed<<endl;
        edge[++num].ed=ed;
        edge[num].nex=first[st];
        first[st]=num;
    }
    void addc(int st,int ed){
    //    cout<<"Stc="<<st<<" edc="<<ed<<endl;
        edgec[++numc].ed=ed;
        edgec[numc].nex=firstc[st];
        firstc[st]=numc;
    }
    void tarjan(int x){
        dfn[x]=low[x]=++ord;
        sta[++top]=x;ins[x]=1;
        for(int i=first[x];i;i=edge[i].nex){
            int y=edge[i].ed;
            if(!dfn[y]){
                tarjan(y);
                low[x]=min(low[x],low[y]);
            }else if(ins[y])
                low[x]=min(low[x],dfn[y]);
        }if(dfn[x]==low[x]){
            sccnum++;int p;
            do{
                p=sta[top--];ins[p]=0;
                bl[p]=sccnum;scc[sccnum].push_back(p);
            }while(p!=x);
        }
    }
    void topsort(){
        queue<int>q;
        for(int i=1;i<=sccnum;i++)
            if(du[i]==0) q.push(i);
        while(!q.empty()){
            int x=q.front();q.pop();
        //    cout<<x<<" ";
            for(int i=firstc[x];i;i=edgec[i].nex){
                int y=edgec[i].ed;
                du[y]--;
                s[y]|=s[x];
                if(du[y]==0)
                    q.push(y);
            }
        }
    }
    int main(){
    //    freopen("a,in","r",stdin);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",ch+1);
            for(int j=1;j<=n;j++)
                if(ch[j]-'0')
                    add(i,j);
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        for(int i=1;i<=n;i++)
            for(int j=first[i];j;j=edge[j].nex){
                int y=edge[j].ed;
                if(bl[i]==bl[y]) continue;
                addc(bl[i],bl[y]);
                du[bl[y]]++;
            }
        for(int i=1;i<=sccnum;i++){
            for(int j=0;j<scc[i].size();j++){
                int y=scc[i][j];
                s[i][y]=1;
            }        
        }
        topsort();
        for(int i=1;i<=sccnum;i++)
            ans+=s[i].count()*scc[i].size();
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    js中(function(){…})()立即执行函数写法理解
    css3 样式 圆角
    Hbuilder实用技巧
    开始使用 HBuilder 和 Mui
    init和plus(编码中遇到问题就看这里)
    将id传过去,根据id显示下面的详情页面
    iOS-上传头像的使用
    iOS-iOS 支付 [支付宝、银联、微信](转)
    iOS-ShareSDK的使用(转)
    iOS-在AFN基础上进行网络请求的封装
  • 原文地址:https://www.cnblogs.com/Yu-shi/p/11183135.html
Copyright © 2011-2022 走看看