标签:tarjan,bitset,拓扑排序
Description
Input
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。
Output
输出一行一个整数,表示该图的连通数。
Sample Input
3
010
001
100
Sample Output
9
HINT
对于100%的数据,N不超过2000。
分析:
Tarjan缩点重新构图
F[i][j]表示i和j点之间的联通情况,然后按照拓扑序从后往前整体取或,最后用每个联通块的大小来更新答案
Code
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int i=a;i<=b;i++) #define dep(i,a,b) for(int i=a;i>=b;i--) #define ll long long #define mem(x,num) memset(x,num,sizeof x) #ifdef WIN32 #define LL "%I64d" #else #define LL "%lld" #endif using namespace std; inline ll read() { ll f=1,x=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int maxn=2006; int n,cnt=0,scc,top=0,tim,lim,ans=0; int head[maxn],h[maxn],r[maxn],dfn[maxn],low[maxn],que[maxn],inque[maxn]; int belong[maxn],hav[maxn],mark[maxn][maxn]; char ch[maxn]; struct edge{int to,next;}e[4000006],ed[4000006]; #define reg(x) for(int i=head[x];i;i=e[i].next) #define v e[i].to #define newreg(x) for(int i=h[x];i;i=ed[i].next) #define newv ed[i].to void tarjan(int x) { int now=0; dfn[x]=low[x]=++tim;que[++top]=x;inque[x]=1; reg(x) if(!dfn[v]){tarjan(v);low[x]=min(low[x],low[v]);} else if(inque[v])low[x]=min(low[x],dfn[v]); if(low[x]==dfn[x]){ scc++; while(now!=x){ now=que[top--]; inque[now]=0;belong[now]=scc;hav[scc]++; } } } void rebuild() { cnt=0; rep(k,1,n) reg(k) if(belong[k]!=belong[v])ed[++cnt]=(edge){belong[k],h[belong[v]]},h[belong[v]]=cnt,r[belong[k]]++; } int main() { n=read(); lim=n/30+1; rep(i,1,n){ scanf("%s",ch); rep(j,1,n) if(ch[j-1]-'0')e[++cnt]=(edge){j,head[i]},head[i]=cnt; } rep(i,1,n) if(!dfn[i])tarjan(i); rebuild(); top=0;int now; rep(i,1,n)mark[belong[i]][i/30+1]|=(1<<(i%30)); rep(i,1,scc)if(!r[i])que[++top]=i; while(top){ now=que[top--]; newreg(now){ rep(j,1,lim)mark[newv][j]|=mark[now][j]; r[newv]--; if(!r[newv])que[++top]=newv; } } rep(i,1,scc) rep(j,1,n) if((mark[i][j/30+1])&(1<<(j%30)))ans+=hav[i]; cout<<ans<<endl; return 0; }