1. 程式人生 > >BZOJ2208 [Jsoi2010]連通數 【圖的遍歷】

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; }