Tarjan, state compression.
First, direct violence can be done.
The first step Tarjan the component, and the graph becomes a dag. Run a topological sort.
Then reverse with a f[i] binary array representing the points I can reach.
A bitset is used because 2000 points are not known to fit in the data type.
Then the answer is sum (size[u]*size[v]) F[u][v]=1,u can go to v.
#include <cstdio>#include<algorithm>#include<cstring>#include<bitset>using namespacestd;Const intMAXN = -+Ten;Const intMAXM =4000000+Ten;intG[maxn],v[maxm],next[maxm],eid;intLow[maxn],dfn[maxn],color[maxn],size[maxn],vis[maxn],s[maxn],sp,vid,cid;intQ[maxn],l,r;bitset<maxn>F[MAXN];intN,res;voidAddedge (intAintb) {V[eid]=b; Next[eid]=g[a]; g[a]=eid++; }voidbuild () {memset (G,-1,sizeof(G)); scanf ("%d",&N); for(intI=1, t;i<=n;i++) for(intj=1; j<=n;j++) {scanf ("%1d",&t); if(t) Addedge (I,J); }}voidTarjan (intu) {Dfn[u]=low[u]=++vid; s[++sp]=u; vis[u]=1; for(intI=g[u];~i;i=Next[i]) { if(vis[v[i]]==0) {Tarjan (v[i]); Low[u]=min (Low[u],low[v[i]]); } Else if(vis[v[i]]==1) Low[u]=min (Low[u],dfn[v[i]]); } if(low[u]==Dfn[u]) { ++CID; Do{COLOR[S[SP]]=CID; SIZE[CID]++; VIS[S[SP]]=2; } while(s[sp--]!=u); }}intG[MAXN],V[MAXM],NEXT[MAXM],inch[Maxn],eid;voidAddedge (intAintb) {V[eid]=b; Next[eid]=g[a]; g[a]=eid++; inch[b]++; }voidPredo () { for(intI=1; i<=n;i++)if(!Vis[i]) Tarjan (i); Memset (g,-1,sizeof(g)); for(intu=1; u<=n;u++) for(intI=g[u];~i;i=Next[i])if(color[u]!=Color[v[i]]) Addedge (Color[u],color[v[i]);}voidToposort () {L=r=1; for(intI=1; i<=cid;i++)if(!inch[i]) q[r++]=i; while(l<r) {intu=q[l++]; for(intI=g[u];~i;i=next[i])if(!--inch[V[i]]) q[r++]=V[i]; } }voidsolve () {toposort (); for(intI=1; i<=cid;i++) f[i][i]=1; for(intx=r-1, u;x;x--) {u=Q[x]; for(intI=g[u];~i;i=Next[i]) F[u]|=F[v[i]]; } for(intI=1; i<=cid;i++) for(intj=1; j<=cid;j++) if(F[i][j]) res+=size[i]*Size[j]; printf ("%d\n", res);}intMain () {build (); Predo (); Solve (); return 0;}
bzoj2208: [Jsoi2010] Connectivity number