bzoj2208:[Jsoi2010]连通数

Posted BBChq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",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]

以上是关于bzoj2208:[Jsoi2010]连通数的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 2208[Jsoi2010]连通数

bzoj2208[Jsoi2010]连通数

bzoj 2208: [Jsoi2010]连通数

bzoj2208 [Jsoi2010]连通数

BZOJ2208: [Jsoi2010]连通数

[bzoj2208][Jsoi2010]连通数