bzoj2208 [Jsoi2010]连通数

题目链接

先是强连通分量缩点,然后出来一个DAG

然后就可以DP啦,要找出每个SCC能到达的SCC有哪些

如果直接存一个二维数组来传递闭包的话肯定会TLE对吧

于是我们使用了神奇的bitset就快多了

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<iostream>
 4 #include<bitset>
 5 #include<set>
 6 #include<map>
 7 #include<queue>
 8 #include<stack>
 9 #include<cmath>
10 #include<algorithm>
11 #include<string>
12 #include<string>
13 #define re(i,l,r) for(int i=(l);i<=(r);i++)
14 #define rre(i,l,r) for(int i=(l);i>=(r);i--)
15 using namespace std;
16 void inin(int &x)
17 {
18     x=0;int f=0;char ch=getchar();
19     while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
20     while(ch>='0'&&ch<='9')x*=10,x+=ch-'0',ch=getchar();
21     x=f?-x:x;
22 }
23 int head[2020],next[4000040],zhi[4000040],s[2020];
24 int head2[2020],next2[4000040],zhi2[4000040];
25 int low[2020],dfn[2020],sccno[20020],tot,sum,ed;
26 void add(int a,int b)
27 {
28     next[++ed]=head[a],head[a]=ed,zhi[ed]=b;
29 }
30 int r[2020];
31 void add2(int a,int b)
32 {
33     next2[++ed]=head2[a],head2[a]=ed,zhi2[ed]=b,r[b]++;
34 }
35 stack<int>h;
36 void dfs(int u)
37 {
38     dfn[u]=low[u]=++tot;
39     h.push(u);
40     for(int i=head[u];i;i=next[i])
41     {
42         int v=zhi[i];
43         if(!dfn[v])dfs(v),low[u]=min(low[u],low[v]);
44         else if(!sccno[v])low[u]=min(low[u],dfn[v]);
45     }
46     if(low[u]==dfn[u])
47     {
48         sum++;
49         while(1)
50         {
51             int x=h.top();h.pop();
52             sccno[x]=sum;
53             s[sum]++;
54             if(x==u)break;
55         }
56     }
57 }
58 int n,mm[2020][2020];
59 void rebuild()
60 {
61     ed=0;
62     re(i,1,n)for(int j=head[i];j;j=next[j])
63         if(sccno[i]!=sccno[zhi[j]]&&!mm[sccno[i]][sccno[zhi[j]]])
64             add2(sccno[i],sccno[zhi[j]]),mm[sccno[i]][sccno[zhi[j]]]=1;
65 }
66 queue<int>hh;
67 bitset<2020> dp[2020];
68 int main()
69 {
70     freopen("in.in","r",stdin);
71     freopen("out.out","w",stdout);
72     inin(n);
73     char ss[2020];
74     re(i,1,n)
75     {
76         scanf("%s",ss+1);
77         re(j,1,n)if(ss[j]=='1')add(i,j);
78     }
79     re(i,1,n)if(!dfn[i])dfs(i);
80     rebuild();int ans=0;
81     re(i,1,sum){if(!r[i])hh.push(i);dp[i][i]=1;}
82     while(!hh.empty())
83     {
84         int x=hh.front();hh.pop();
85         for(int i=head2[x];i;i=next2[i])
86         {
87             r[zhi2[i]]--;dp[zhi2[i]]|=dp[x];
88             if(!r[zhi2[i]])hh.push(zhi2[i]);
89         }
90     }
91     re(i,1,sum)
92     {
93         int u=0;
94         re(j,1,sum)if(dp[i][j]==1)u+=s[j];
95         ans+=s[i]*u;
96     }
97     printf( "%d\n",ans);
98     return 0;
99 }

 

你可能感兴趣的:(bzoj2208 [Jsoi2010]连通数)