2208: [Jsoi2010]连通数
Time Limit: 20 Sec
Memory Limit: 512 MB
Submit: 2241
Solved: 959
Description
Input
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。
Output
输出一行一个整数,表示该图的连通数。
Sample Input
3
010
001
100
010
001
100
Sample Output
9
HINT
对于100%的数据,N不超过2000。
题解:
缩点之后对每个点进行Dfs就可以啦#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=2000005;
const int N=2005;
bool used[2005];
int bel[N],w[N],n,m,ans,tot,tott,ff[M],tt[M];
int from[M],nxt[M],lj[N],to[M],cnt;
void insert(int f,int t)
{
cnt++;
from[cnt]=f;
to[cnt]=t;
nxt[cnt]=lj[f];
lj[f]=cnt;
}
int dfn[N],low[N],s[N],h;
bool ins[N];
void pop()
{
bel[s[h]]=tot;
w[tot]++;
ins[s[h]]=false;
h--;
}
void Tarjan(int x)
{
dfn[x]=low[x]=++cnt;
s[++h]=x;
ins[x]=true;
for(int i=lj[x];i;i=nxt[i])
{
if(!dfn[to[i]])
{
Tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(ins[to[i]]) low[x]=min(low[x],low[to[i]]);
}
if(dfn[x]==low[x])
{
tot++;
while(s[h]!=x) pop();
pop();
}
}
void dfs(int x)
{
tott+=w[x];
used[x]=1;
for(int i=lj[x];i;i=nxt[i])
if(!used[to[i]]) dfs(to[i]);
}
int main()
{
scanf("%d",&n);
char c;
for(int i=1;i<=n;i++)
{
scanf("\n");
for(int j=1;j<=n;j++)
{
scanf("%c",&c);
if(c=='1')
{
insert(i,j);
m++;
ff[m]=i,tt[m]=j;
}
}
}
cnt=0;
for(int i=1;i<=n;i++)
if(!dfn[i]) Tarjan(i);
memset(lj,0,sizeof(lj));
cnt=0;
for(int i=1;i<=m;i++) insert(bel[ff[i]],bel[tt[i]]);
for(int i=1;i<=tot;i++)
{
memset(used,0,sizeof(used));
tott=0;
dfs(i);
ans+=w[i]*tott;
}
printf("%d",ans);
}
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=2000005;
const int N=2005;
bool used[2005];
int bel[N],w[N],n,m,ans,tot,tott,ff[M],tt[M];
int from[M],nxt[M],lj[N],to[M],cnt;
void insert(int f,int t)
{
cnt++;
from[cnt]=f;
to[cnt]=t;
nxt[cnt]=lj[f];
lj[f]=cnt;
}
int dfn[N],low[N],s[N],h;
bool ins[N];
void pop()
{
bel[s[h]]=tot;
w[tot]++;
ins[s[h]]=false;
h--;
}
void Tarjan(int x)
{
dfn[x]=low[x]=++cnt;
s[++h]=x;
ins[x]=true;
for(int i=lj[x];i;i=nxt[i])
{
if(!dfn[to[i]])
{
Tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(ins[to[i]]) low[x]=min(low[x],low[to[i]]);
}
if(dfn[x]==low[x])
{
tot++;
while(s[h]!=x) pop();
pop();
}
}
void dfs(int x)
{
tott+=w[x];
used[x]=1;
for(int i=lj[x];i;i=nxt[i])
if(!used[to[i]]) dfs(to[i]);
}
int main()
{
scanf("%d",&n);
char c;
for(int i=1;i<=n;i++)
{
scanf("\n");
for(int j=1;j<=n;j++)
{
scanf("%c",&c);
if(c=='1')
{
insert(i,j);
m++;
ff[m]=i,tt[m]=j;
}
}
}
cnt=0;
for(int i=1;i<=n;i++)
if(!dfn[i]) Tarjan(i);
memset(lj,0,sizeof(lj));
cnt=0;
for(int i=1;i<=m;i++) insert(bel[ff[i]],bel[tt[i]]);
for(int i=1;i<=tot;i++)
{
memset(used,0,sizeof(used));
tott=0;
dfs(i);
ans+=w[i]*tott;
}
printf("%d",ans);
}