Kosaraju算法,然後bitset優化
主要是學習一下自寫bitset的姿勢
#include<cstring> #include<algorithm> #include<cstdio> #include<cmath> #define rep(i,l,r) for(int i=l;i<=r;i++) #define dow(i,l,r) for(int i=r;i>=l;i--) #define rep0(i,r) for(int i=0;i<r;i++) #define repedge(i,x) for(int i=cur[x];i>=0;i=e[i].next) #define maxn 550 #define maxm 100100 #define LL long long using namespace std; int tot,p[maxn],n,m,kk; char s[maxn]; struct Bitset{ unsigned int v[8]; void reset() //clear { memset(v,0,sizeof(v)); } void set(int x) //set v[x]=1 { v[x>>5]|=1u<<(x&31); } void flip(int x) // rev { v[x>>5]^=1u<<(x&31); } bool ask(int x) // is == 1? { return v[x>>5]>>(x&31)&1; } }vis,g[maxn],rg[maxn]; //vis[] =1 not vis,=0 vis //g[i][j] =1 exist i->j,=0 not exist //rg[i][j] =1 exist j->i,=0 not exist; void add(int j,int k) { g[j].flip(k); rg[k].flip(j); } int nlz(unsigned int x) { int n; n = 1; if ((x >> 16) == 0) {n = n +16; x = x <<16;} if ((x >> 24) == 0) {n = n + 8; x = x << 8;} if ((x >> 28) == 0) {n = n + 4; x = x << 4;} if ((x >> 30) == 0) {n = n + 2; x = x << 2;} n = n - (x >> 31); return 31-n; } void dfs0(int x) { vis.flip(x); rep0(i,8) { unsigned int now=vis.v[i]&g[x].v[i]; while (now) { dfs0(i<<5|nlz(now)); now=vis.v[i]&g[x].v[i]; } } p[++tot]=x; } void dfs1(int x) { vis.flip(x); ++tot; rep0(i,8) { unsigned int now=vis.v[i]&rg[x].v[i]; while (now) { dfs1(i<<5|nlz(now)); now=vis.v[i]&rg[x].v[i]; } } } int calc() { vis.reset(); rep0(i,n) vis.set(i); tot=0; rep0(i,n) if (vis.ask(i)) dfs0(i); rep0(i,n) vis.set(i); int ans=0; dow(i,1,n) if (vis.ask(p[i])) { tot=0; dfs1(p[i]); ans+=tot*(tot-1)/2; } return ans; } int main() { int tt; scanf("%d",&tt); while (tt--) { scanf("%d %d",&n,&m); rep0(i,n) { g[i].reset(); rg[i].reset(); } rep0(i,n) { scanf("%s",s); rep0(j,n) if (s[j]=='1') add(i,j); } while (m--) { scanf("%d",&kk); while (kk--) { int j,k; scanf("%d %d",&j,&k); add(j-1,k-1); } printf("%d\n",calc()); } } return 0; }