BZOJ2208 [JSOI2010] 连通数

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2208

Description

Input

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

Output

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

 

Tarjan缩点+拓扑排序+bitset,mark[i][j]中的i表示第i个强连通分量,每一个点j对应mark[i][j/30+1]从右边数起第j%30位。

每一个点与一个强连通分量连通的答案贡献值等于该强连通分量的大小

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <stack>
 6 #include <queue>
 7 #define rep(i,l,r) for(int i=l; i<=r; i++)
 8 #define clr(x,y) memset(x,y,sizeof(x))
 9 #define travel(x) for(int i=last[x]; i; i=edge[i].pre)
10 #define travel2(x) for(int i=last2[x]; i; i=edge2[i].pre)
11 using namespace std;
12 const int maxn = 2010;
13 struct Edge{
14     int pre,to;
15 }edge[maxn*maxn],edge2[maxn*maxn];
16 int n,m,x,now,maxx,tot=0,tot2=0,ans=0,scc=0,dfsclock=0;
17 int last[maxn],last2[maxn],dfn[maxn],low[maxn],belong[maxn],cnt[maxn],ind[maxn],mark[maxn][70];
18 char ch[maxn];
19 bool isin[maxn];
20 stack <int> s;
21 queue <int> q;
22 inline void addedge(int x,int y){
23     edge[++tot].pre = last[x];
24     edge[tot].to = y;
25     last[x] = tot;
26 }
27 inline void addedge2(int x,int y){
28     edge2[++tot2].pre = last2[x];
29     edge2[tot2].to = y;
30     last2[x] = tot2;
31     ind[y]++;
32 }
33 void tarjan(int x){
34     dfn[x] = low[x] = ++dfsclock;
35     isin[x] = 1; s.push(x);
36     travel(x){
37         if (!dfn[edge[i].to]){
38             tarjan(edge[i].to);
39             low[x] = min(low[x],low[edge[i].to]);
40         }
41         else if (isin[edge[i].to]) low[x] = min(low[x],dfn[edge[i].to]);
42     }
43     if (dfn[x] == low[x]){
44         scc++;
45         while (s.top() != x){
46             isin[s.top()] = 0;
47             belong[s.top()] = scc;
48             cnt[scc]++;
49             s.pop();
50         }
51         isin[x] = 0; belong[x] = scc; cnt[scc]++; s.pop();
52     }
53 }
54 void toposort(){
55     clr(mark,0);
56     rep(i,1,n) mark[belong[i]][i/30+1] |= (1 << (i % 30));
57     rep(i,1,scc) if (!ind[i]) q.push(i);
58     while (!q.empty()){
59         now = q.front(); q.pop();
60         travel2(now){
61             rep(j,1,maxx) mark[edge2[i].to][j] |= mark[now][j];
62             ind[edge2[i].to]--;
63             if (!ind[edge2[i].to]) q.push(edge2[i].to);
64         }
65     }
66 }
67 int main(){
68     scanf("%d",&n); clr(last,0); clr(last2,0); clr(mark,0); maxx = n / 30 + 1;
69     rep(i,1,n){
70         scanf("%s",ch);
71         rep(j,1,n) if (ch[j-1] - '0') addedge(i,j);
72     }
73     clr(isin,0); clr(dfn,0); clr(cnt,0);
74     rep(i,1,n) if (!dfn[i]) tarjan(i);
75     clr(ind,0);
76     rep(now,1,n) travel(now) if (belong[now] != belong[edge[i].to])
77         addedge2(belong[now],belong[edge[i].to]);
78     toposort();
79     rep(i,1,scc) rep(j,1,n)
80     if (mark[i][j/30+1] & (1 << (j % 30))) ans += cnt[i];
81     printf("%d\n",ans);
82     return 0;
83 }
View Code

 

posted on 2015-12-07 18:29  ACMICPC  阅读(271)  评论(0编辑  收藏  举报

导航