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]

时间: 2024-11-05 11:22:27

bzoj2208:[Jsoi2010]连通数的相关文章

[bzoj2208][Jsoi2010]连通数

来自FallDream的博客,未经允许,请勿转载,谢谢. n<=2000 bitset优化floyd , 枚举k,枚举i,如果i能到k,那么i的bitset直接或上k的.复杂度$O(\frac{n^{3}}{32})$ #include<iostream> #include<cstdio> #include<bitset> #define MN 2000 using namespace std; inline int read() { int x = 0 , f

bzoj2208: [Jsoi2010]连通数 缩点+拓扑+状压

tarjan缩点后拓扑排序,每一个点用一个bitset记录哪些点能到达它. PS:数据太水,暴力能过. #include<bits/stdc++.h> using namespace std; #define N 2010 struct edge{ edge* s; int v; }e[N*N*2],*back=e,*h[N]; int low[N],num[N],scc[N],size[N]; int now; void tarjan(int u){ static int cnt; stat

【强联通分量缩点】【搜索】bzoj2208 [Jsoi2010]连通数

两次dfs缩点,然后n次dfs暴搜. 1 #include<cstdio> 2 #include<vector> 3 #include<cstring> 4 using namespace std; 5 #define N 2001 6 vector<int>G[N],rG[N],vs,G2[N]; 7 typedef vector<int>::iterator ITER; 8 char s[N+1][N+1]; 9 int cmp[N],sum

[BZOJ2208][JSOI2010]连通数(传递闭包+bitset)

正解好象是tarjan缩点处理. 1 #include<cstdio> 2 #include<bitset> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=l; i<=r; i++) 5 using namespace std; 6 7 const int N=2010; 8 int n,ans; 9 char x; 10 bitset<N>f[N]; 11 12 int main(){ 1

【bzoj2208】[Jsoi2010]连通数

2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2305  Solved: 989[Submit][Status][Discuss] Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. Output 输出一行一个整数,表示该图的连通数. Sample Input 3 010 001 100 Sample

2208: [Jsoi2010]连通数

2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1371  Solved: 557[Submit][Status] Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. Output 输出一行一个整数,表示该图的连通数. Sample Input 3 010 001 100 Sample Output 9

2208: [Jsoi2010]连通数 - BZOJ

Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. Output 输出一行一个整数,表示该图的连通数. Sample Input 3 010 001 100 Sample Output 9HINT 对于100%的数据,N不超过2000. 看到这题然后马上打了一个tarjan 然后对每一个强连通分量dfs,A了之后感觉有点奇怪,这个复杂度是多少来着,我好像算不出来,果断百度题解 然后大囧..

BZOJ 2208: [Jsoi2010]连通数( DFS )

n只有2000,直接DFS就可以过了... -------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<cctype> #define rep( i, n ) for( int i = 0; i

【BZOJ 2208】 [Jsoi2010]连通数

2208: [Jsoi2010]连通数 Time Limit: 20 Sec  Memory Limit: 512 MB Submit: 1431  Solved: 585 [Submit][Status][Discuss] Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. Output 输出一行一个整数,表示该图的连通数. Sample Input 3 010 001 100 Samp