BZOJ2208 [Jsoi2010]连通数 【图的遍历】
题目
输入格式
输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。
输出格式
输出一行一个整数,表示该图的连通数。
输入样例
3
010
001
100
输出样例
9
提示
对于100%的数据,N不超过2000。
题解
今晚水的题有点多。。。【明天要会考涨涨信心】
N才2000,可以
那从每个点出发跑一遍bfs看看能到哪些点就好了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
using namespace std;
const int maxn = 2005,maxm = 5000005,INF = 1000000000;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int h[maxn],ne = 0,ans = 0,n,vis[maxn];
struct EDGE{int to,nxt;}ed[maxm];
inline void build(int u,int v){ed[ne] = (EDGE){v,h[u]}; h[u] = ne++;}
queue<int> q;
void bfs(int u){
memset(vis,0,sizeof(vis));
q.push(u); vis[u] = true;
while (!q.empty()){
u = q.front(); q.pop();
ans++;
Redge(u) if (!vis[ed[k].to]) q.push(ed[k].to),vis[ed[k].to] = true;
}
}
int main(){
memset(h,-1,sizeof(h));
n = RD(); char c;
REP(i,n) REP(j,n){
c = getchar();
while (c != '1' && c != '0') c = getchar();
if (c == '1') build(i,j);
}
REP(i,n) bfs(i);
printf("%d\n",ans);
return 0;
}