[Jsoi2010]连通数
时间限制: 10 Sec 内存限制: 512 MB
题目描述
Input
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。
Output
输出一行一个整数,表示该图的连通数。
Sample Input
3
010
001
100
Sample Output
9
HINT
对于100%的数据,N不超过2000。
这里必须d一下出题人,我floyd都过了
代码:
暴力
我明明就超了270ms
#include<bits/stdc++.h>
using namespace std;
bitset<2010>a[2010];
int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
char k;
for(int j=1;j<=n;j++)
{
cin>>k;
if(k=='1')
a[i][j]=1;
}
a[i][i]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[j][i]==1)
{
a[j]|=a[i];
}
long long ans=0;
for(int i=1;i<=n;i++)
ans+=a[i].count();
printf("%lld",ans);
}
手动开O2
臭不要脸
#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
int f[2020][2020];
char a[2020][2020];
int main()
{
int n,ans=0;
char ch;
scanf("%d",&n);
for(register int i=1; i<=n; i++) {
scanf("%s",a[i]);
for(int j=0; j<n; j++) {
if(a[i][j]=='1')f[i][j+1]=1;
}
f[i][i]=1;
}
for(register int k=1; k<=n; k++) {
for(register int i=1; i<=n; i++) {
for(register int j=1; j<=n; j++) {
if(f[i][k]&f[k][j])f[i][j]=1;
}
}
}
for(register int i=1; i<=n; i++) {
for(register int j=1; j<=n; j++) {
if(f[i][j])ans++;
}
}
printf("%d\n",ans);
}
算了,来个正确的……
#include<bits/stdc++.h>
using namespace std;
bitset<2010>a[2010];//常数优化1/32
int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
char k;
for(int j=1;j<=n;j++)
{
cin>>k;
if(k=='1')
a[i][j]=1;
}
a[i][i]=1;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(a[j][i]==1)
{
a[j]|=a[i];
}
long long ans=0;
for(int i=1;i<=n;i++)
ans+=a[i].count();
printf("%lld",ans);
}
虽然正解是拓扑排序+强连通分量缩点+bitset
有大佬会吗?
蒟蒻一枚,请各位神犇指导, Q Q : 736731592 QQ:736731592 QQ:736731592。
查看正解见https://blog.youkuaiyun.com/dhdhdhx.