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 }