当前位置: 代码迷 >> 综合 >> BZOJ2208 [Jsoi2010]连通数 【图的遍历】
  详细解决方案

BZOJ2208 [Jsoi2010]连通数 【图的遍历】

热度:14   发布时间:2023-12-25 04:48:37.0

题目

这里写图片描述

输入格式

输入数据第一行是图顶点的数量,一个正整数N。 接下来N行,每行N个字符。第i行第j列的1表示顶点i到j有边,0则表示无边。

输出格式

输出一行一个整数,表示该图的连通数。

输入样例

3

010

001

100

输出样例

9

提示

对于100%的数据,N不超过2000。

题解

今晚水的题有点多。。。【明天要会考涨涨信心
N才2000,可以O(n2)
那从每个点出发跑一遍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;
}