zoukankan      html  css  js  c++  java
  • bzoj2208:[Jsoi2010]连通数

    http://blog.csdn.net/u013598409/article/details/47037499 里面似乎有生成数据的。。。
    //我本来的想法是tarjan缩点之后然后将图遍历一遍就可以了,复杂度应该是O(n2)的,为什么说这样是n3的啊。。。
    //=>这种做法是错的因为有可能会重复计算用一下传递闭包就可以了然而直接递推以前写的dfsqaq
    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<algorithm>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<bitset>
    using namespace std;
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define clr(x,c) memset(x,c,sizeof(x))
    #define qwq(x) for(edge *o=head[x];o;o=o->next)
    const int nmax=2e3+5;
    const int maxn=nmax*nmax;
    const int inf=0x7f7f7f7f;
    struct edge{
        int to;edge *next;
    }; 
    edge es[maxn],*pt=es,*head[nmax];
    void add(int u,int v){
        pt->to=v;pt->next=head[u];head[u]=pt++;
    }
    char ch[nmax];
    int pre[nmax],scc_cnt,dfs_clock,sm[nmax],scc[nmax];
    stack<int>s;
    void mins(int &a,int b){
        if(a>b) a=b;
    }
    int dfs(int x){
        int lowu=pre[x]=++dfs_clock;s.push(x);
        qwq(x){
            if(!pre[o->to]) mins(lowu,dfs(o->to));
            if(!scc[o->to]) mins(lowu,pre[o->to]);
        }
        if(lowu==pre[x]){
            scc_cnt++;int o,cnt=0;
            while(1){
                o=s.top();s.pop();
                scc[o]=scc_cnt;++cnt;
                if(o==x) break;
            }
            sm[scc_cnt]=cnt;
        }
        return lowu;
    }
    bitset<nmax>a[nmax];
    int in[nmax];vector<int>g[nmax];queue<int>q;
    int main(){
        int n,u,v,d;scanf("%d",&n);
        rep(i,1,n){
            scanf("%s",ch+1);
            rep(j,1,n) if(ch[j]=='1') add(i,j);
        }
        rep(i,1,n) if(!pre[i]) dfs(i);
         
        rep(i,1,n) {
            u=scc[i];
            qwq(i) if(u!=(v=scc[o->to])) g[u].push_back(v),++in[v];
        }
        rep(i,1,scc_cnt) a[i][i]=1;
        rep(i,1,scc_cnt) if(!in[i]) q.push(i);
        while(!q.empty()){
            u=q.front();q.pop();
            if(!g[u].size()) continue;
            rep(i,0,g[u].size()-1){
                v=g[u][i];
                a[v]|=a[u]; //a保存的是可以到达该强联通分量的 
                if(!--in[v]) q.push(v);
            }
        }
        int ans=0;
        rep(i,1,scc_cnt) rep(j,1,scc_cnt) if(a[i][j]) ans+=sm[i]*sm[j];
        printf("%d
    ",ans);
        return 0;
    }
    

    2208: [Jsoi2010]连通数

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 2249  Solved: 965
    [Submit][Status][Discuss]

    Description

    Input

    输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。

    Output

    输出一行一个整数,表示该图的连通数。

    Sample Input

    3
    010
    001
    100

    Sample Output

    9

    HINT

    对于100%的数据,N不超过2000。

    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    假期学习2
    假期学习1
    读《需求工程--软件建模和分析》一
    数据清洗
    Mapreduce实例——WordCount
    SEVEN python环境jieba分词的安装 以即热词索引
    SIX Spark Streaming 编程初级实践
    FIVE Spark SQL 编程初级实践
    FOUR spark-shell 交互式编程
    THREE SPAKR
  • 原文地址:https://www.cnblogs.com/fighting-to-the-end/p/5858060.html
Copyright © 2011-2022 走看看