2208: [Jsoi2010]连通数
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2028 Solved: 855
[ Submit][ Status][ Discuss]
Description
Input
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。
Output
输出一行一个整数,表示该图的连通数。
Sample Input
010
001
100
Sample Output
HINT
对于100%的数据,N不超过2000。
解题思路:先强连通分量求出来,然后每一个分量bfs一遍(我只会这个)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
int n,len,len1,head,tail,size,tcc;
int to[4000011],next[4000011],h[2010];
int to1[4000011],next1[4000011],h1[2010];
int q[4000011];
int dfn[2010],twf[2010];
int biao[2010],dui[2010],sg[2010];
bool b[2010][2010];
int ru[2010];
int sum[2010];
bool g[2010];
inline int read()
{
char y; int x=0,f=1; y=getchar();
while (y<'0' || y>'9') {if (y=='-')f=-1; y=getchar();}
while (y>='0' && y<='9') {x=x*10+int(y)-48; y=getchar();}
return x*f;
}
void insert(int x,int y)
{
++len; to[len]=y; next[len]=h[x]; h[x]=len;
}
void insert1(int x,int y)
{
++len1; to1[len1]=y; next1[len1]=h1[x]; h1[x]=len1;
}
void dfs(int x,int fa)
{
++head; q[head]=x;
++size; dfn[x]=twf[x]=size; biao[x]=1;
int u=h[x];
while (u!=0)
{
if (to[u]!=fa && dfn[to[u]]==-1)
{
dfs(to[u],x);
twf[x]=min(twf[x],twf[to[u]]);
}else
if (biao[to[u]]==1) twf[x]=min(twf[x],twf[to[u]]);
u=next[u];
}
if (twf[x]==dfn[x])
{
++tcc;
while (q[head]!=x)
{
biao[q[head]]=2;
dui[q[head]]=tcc; ++sg[tcc];
--head;
}
biao[x]=2;
dui[x]=tcc; ++sg[tcc]; --head; sum[tcc]=sg[tcc];
}
}
int main()
{
n=read();
for (int i=1;i<=n;++i)
{
char c[2100];
scanf("%s",c);
int len=strlen(c);
for (int j=1;j<=len;++j)
if (c[j-1]=='1')
{
insert(i,j);
}
}
tcc=0; size=0; head=0;
memset(twf,-1,sizeof(twf));
memset(dfn,-1,sizeof(dfn));
memset(biao,-1,sizeof(biao));
for (int i=1;i<=n;++i)
if (dfn[i]==-1)
{
dfs(i,0);
}
memset(b,true,sizeof(b));
for (int i=1;i<=n;++i)
{
int u=h[i];
while (u!=0)
{
if (b[dui[i]][dui[to[u]]]==true && dui[to[u]]!=dui[i])
{
b[dui[i]][dui[to[u]]]=false;
insert1(dui[i],dui[to[u]]);
}
u=next[u];
}
}
long long ans=0;
for (int i=1;i<=tcc;++i)
{
memset(g,true,sizeof(g));
int head=0,tail=1; q[tail]=i; g[i]=false;
while (head<tail)
{
++head;
ans+=sg[i]*sg[q[head]];
int u=h1[q[head]];
while (u!=0)
{
if (g[to1[u]])
{
g[to1[u]]=false; ++tail; q[tail]=to1[u];
}
u=next1[u];
}
}
}
printf("%lld",ans);
}