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

题目

这里写图片描述

输入格式

输入数据第一行是图顶点的数量,一个正整数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;
}
posted @ 2017-12-26 20:44  Mychael  阅读(112)  评论(0编辑  收藏  举报