BZOJ 2208 Jsoi2010 连通数

2208: [Jsoi2010]连通数

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 3328  Solved: 1457
[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

第一轮

暴力n^2是可以过得

正解是tarjin缩完点,递推一下

#include <bits/stdc++.h>
#define ll long long
#define eps 1e-7
using namespace std;
inline int read(){
    int x=0;int f=1;char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=5e6+10;
struct node{
    int y,next;
}e[MAXN];
int linkk[MAXN],len=0,a[2010][2010],low[MAXN],dfs_clock=0,dfn[MAXN],cnt[MAXN],sum[MAXN],f[MAXN],tot=0,vis[2100],n,m,ine[MAXN],stark[MAXN],top=0;
inline void insert(int xx,int yy){
    e[++len].y=yy;e[len].next=linkk[xx];linkk[xx]=len;
}
namespace zhangenming{
    void tarjin(int st){
        dfn[st]=low[st]=++dfs_clock;
        vis[st]=1;stark[++top]=st;
        for(int i=linkk[st];i;i=e[i].next){
            if(!dfn[e[i].y]){
                tarjin(e[i].y);
                low[st]=min(low[st],low[e[i].y]);
            }
            else if(vis[e[i].y]) low[st]=min(low[st],dfn[e[i].y]);
        }
        if(low[st]==dfn[st]){
            ++tot;
            int k;
            do{
                k=stark[top--];
                ine[k]=tot;
                vis[k]=0;
                sum[tot]++;
            }while(k!=st);
        }
    }
    void rebuild(){
        len=0;memset(linkk,0,sizeof(linkk));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(ine[i]!=ine[j]&&a[i][j]){
                    insert(ine[i],ine[j]);
                    cnt[ine[j]]++;
                }
            }
        }
    }
    void init(){
        n=read();
        for(int i=1;i<=n;i++){
            char ch[2100];
            scanf("%s",ch+1);
            for(int j=1;j<=n;j++){
                a[i][j]=ch[j]-'0';
                if(a[i][j]) insert(i,j);
            }
        }
    }
    inline void dp(int st,int tn){
        vis[st]=1;
        for(int i=linkk[st];i;i=e[i].next){
            if(!vis[e[i].y]) dp(e[i].y,tn);
        }
        f[tn]+=sum[st];
    }
    void solve(){
        for(int i=1;i<=n;i++){
            if(!dfn[i]) tarjin(i);
        }
        rebuild();
        //cout<<tot<<endl;
        for(int i=1;i<=tot;i++){
            memset(vis,0,sizeof(vis));
            dp(i,i);
        }
        ll ans=0;
        for(int i=1;i<=tot;i++){
            ans+=(sum[i]*f[i]);
        }
        cout<<ans<<endl;
    }
}
int main(){
    //freopen("All.in","r",stdin);
    //freopen("zh.out","w",stdout);
    using namespace zhangenming;
    init();
    solve();
    return 0;
}

  

 

posted @ 2017-12-15 08:15  zhangenming  阅读(117)  评论(0编辑  收藏  举报