bzoj2208 [Jsoi2010]连通数(scc+bitset)

来源:互联网 发布:mac 命令行 文件夹 编辑:程序博客网 时间:2024/06/05 23:40

2208: [Jsoi2010]连通数

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

第一轮

 

【思路】

    强连通分量+bitset传递闭包。

    求出scc,缩点。对于新的DAG,如果两个scc之间相连则ans+=sccsz[i]*sccsz[j]。利用bitset与递推判断相连。

 

【代码】

 

 1 #include<cstdio> 2 #include<bitset> 3 #include<queue> 4 #include<stack> 5 #include<vector> 6 #include<cstring> 7 #include<iostream> 8 using namespace std; 9 10 const int maxn = 2000+10;11 12 int pre[maxn],lowlink[maxn],sccno[maxn],sccsz[maxn],dfs_clock,scc_cnt;13 vector<int> G[maxn];14 stack<int> S;15 16 int dfs(int u) {17     pre[u]=lowlink[u]=++dfs_clock;18     S.push(u);19     for(int i=0;i<G[u].size();i++) {20         int v=G[u][i];21         if(!pre[v]) {22             dfs(v);23             lowlink[u]=min(lowlink[u],lowlink[v]);24         }25         else if(!sccno[v]) {26             lowlink[u]=min(lowlink[u],pre[v]);27         }28     }29     if(lowlink[u]==pre[u]) {30         scc_cnt++;31         for(;;) {32             int x=S.top(); S.pop();33             sccno[x]=scc_cnt;34             sccsz[scc_cnt]++;35             if(x==u) break;36         }37     }38 }39 void find_scc(int n) {40     memset(pre,0,sizeof(pre));41     memset(sccsz,0,sizeof(sccsz));42     memset(sccno,0,sizeof(sccno));43     scc_cnt=dfs_clock=0;44     for(int i=0;i<n;i++)  45         if(!pre[i]) dfs(i);46 }47 48 bitset<maxn> f[maxn];    //使用bitset 49 int n,in[maxn];50 char s[maxn];51 52 vector<int> Gx[maxn];53 void rebuild() {54     for(int i=1;i<=scc_cnt;i++) in[i]=0;55     for(int i=0;i<n;i++) {56         int u=sccno[i];57         for(int j=0;j<G[i].size();j++) {58             int v=sccno[G[i][j]];59             if(u!=v) Gx[u].push_back(v),in[v]++;60         }61     }62 }63 64 queue<int> q;65 void solve() {66     for(int i=1;i<=scc_cnt;i++) f[i][i]=1;67     for(int i=1;i<=scc_cnt;i++) if(!in[i]) q.push(i);68     while(!q.empty()) {69         int u=q.front(); q.pop();70         for(int i=0;i<Gx[u].size();i++) {71             int v=Gx[u][i];72             f[v]|=f[u];            //传递闭包73             if((--in[v])==0)  q.push(v);74         }75     }76 }77 78 int main() {79     scanf("%d",&n);80     for(int i=0;i<n;i++){81         scanf("%s",s);82         for(int j=0;j<n;j++) {83             if(s[j]-'0') G[i].push_back(j);84         }85     }86     find_scc(n);87     rebuild();88     solve();89     int ans=0;90     for(int i=1;i<=scc_cnt;i++)91     {92         for(int j=1;j<=scc_cnt;j++)93             if(f[i][j]) ans+=sccsz[i]*sccsz[j];94     }95     printf("%d\n",ans);96     return 0;97 }

 

0 0
原创粉丝点击