Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)
var route [][]int

func scanInt() int {
	num, _ := strconv.Atoi(scanString())
	return num
}

func scanString() string {
	sc.Scan()
	return sc.Text()
}

func init() {
	sc.Split(bufio.ScanWords)
}

func dfs(h, w int) {
	if route[h][w] == 0 {
		return
	}

	route[h][w] = 0
	for _, x := range []int{-1, 0, 1} {
		for _, y := range []int{-1, 0, 1} {
			if route[h+x][w+y] == 0 {
				continue
			}
			dfs(h+x, w+y)
		}
	}
}

func main() {
	writer := bufio.NewWriter(os.Stdout)
	for {
		w, h := scanInt(), scanInt()
		if w == 0 && h == 0 {
			break
		}

		route = make([][]int, h+2)
		route[0] = make([]int, w+2)
		for i := 1; i <= h; i++ {
			route[i] = make([]int, w+2)
			for j := 1; j <= w; j++ {
				route[i][j] = scanInt()
			}
		}
		route[h+1] = make([]int, w+2)

		total := 0
		for i := 1; i <= h; i++ {
			for j := 1; j <= w; j++ {
				if route[i][j] == 1 {
					total++
					dfs(i, j)
				}
			}
		}
		fmt.Fprintln(writer, total)
	}
	writer.Flush()
}

C++: #include <iostream>
#include <vector>
#include <map>
#include <set>
using namespace std;

void add_label(map<int,int> &tbl, int a, int b){
	if( a == b ) return;
	if( a > b ) tbl[a] = b;
	else tbl[b] = a;
}

int main(void){
	int w, h;
	while( cin>>w>>h, w||h ) {
		vector<vector<int> > field( h );
		vector<vector<int> > labeled( h );
		for( int i=0; i<h; ++i ) {
			field[i] = vector<int>( w );
			labeled[i] = vector<int>( w );
			for( int j=0; j<w; ++j ) {
				cin>>field[i][j];
				labeled[i][j] = 0;
			}
		}
		int label = 1;
		map<int, int> tbl;
		for( int i=0; i<h; ++i ) {
			for( int j=0; j<w; ++j ) {
				if( field[i][j] ){
					bool f = false;
					if( i ) {
						if( j && labeled[i-1][j-1] ) {
							if(!f) labeled[i][j] = labeled[i-1][j-1];
							f = true;
						}
						if( labeled[i-1][j] ) {
							if(!f) labeled[i][j] = labeled[i-1][j];
							else add_label( tbl, labeled[i][j] ,labeled[i-1][j] );
							f = true;
						}
						if( j < w - 1 && labeled[i-1][j+1] ) {
							if(!f) labeled[i][j] = labeled[i-1][j+1];
							else add_label( tbl, labeled[i][j] ,labeled[i-1][j+1] );
							f = true;
						}
						if( j && labeled[i][j-1] ) {
							if(!f) labeled[i][j] = labeled[i][j-1];
							else add_label( tbl, labeled[i][j] ,labeled[i][j-1] );
							f = true;
						}
						if(!f) labeled[i][j] = ++label;
					} else {
						if( j && labeled[i][j-1] ){
							if(!f) labeled[i][j] = labeled[i][j-1];
							else add_label( tbl, labeled[i][j] ,labeled[i][j-1] );
							f = true;
						}
						if(!f) labeled[i][j] = ++label;
					}
				}
			}
		}
		for( auto x : tbl ) {
			int a = x.first;
			int b = x.second;
			while( tbl.find(b) != tbl.end() ) {
				b = tbl.find(b)->second;
			}
			for( int i=0; i<h; ++i ) {
				for( int j=0; j<w; ++j ) {
					if( labeled[i][j] == a ) labeled[i][j] = b;
				}
			}
		}
		
		for( int i=0; i<h; ++i ) {
			cerr<<"!";
			for( int j=0; j<w; ++j ) {
				cerr<<labeled[i][j];
			}
			cerr<<endl;
		}
		
		set<int> nums;
		nums.insert(0);
		for( int i=0; i<h; ++i ) {
			for( int j=0; j<w; ++j ) {
				nums.insert( labeled[i][j] );
			}
		}
		cout<<nums.size()-1<<endl;
	}
	return 0;
}

C++: # include <algorithm>
# include <cassert>
# include <cctype>
# include <cstdio>
# include <cstdlib>
# include <cstring>
# include <cmath>
# include <iostream>
# include <map>
# include <queue>
# include <set>
# include <sstream>
# include <stack>
# include <string>
# include <vector>
# include <iomanip>

# define rep(i, n) for (int i = 0; i < (int)(n); i++)
# define irep(i, n) for (int i = int(n) - 1; i >= 0; i--)
# define FOR(i, m, n) for (int i = int(m); i < (int)(n); i++)

using namespace std;
int w, h, ans;

template <typename T>
void show_all(T t) {
  rep (i, t.size()) {
    rep (j, t[0].size()) {
      cout << setfill('0') << setw(5) << t[i][j] << ' ';
    }
    cout << endl;
  }
  cout << endl;
}


void dfs(vector<vector<int>> &c, int i, int j) {
  vector<int> next_i = {0, 1, 1, 1, 0, -1, -1, -1};
  vector<int> next_j = {1, 1, 0, -1, -1, -1, 0, 1};

  rep (k, 8) {
    int ii = i + next_i[k];
    int jj = j + next_j[k];

    if (0 <= ii && 0 <= jj && ii < c.size() && jj < c[0].size() && c[ii][jj] == 1) {
      c[ii][jj] = 1000;
      dfs(c, ii, jj);
    }
  }
}


int main() {

  while (cin >> w >> h && w && h) {
    vector<vector<int>> c;
    ans = 0;

    rep (i, h) c.push_back(vector<int>(w));
    rep (i, h) {
      rep (j, w) {
        cin >> c[i][j];
      }
    }

    rep (i, h) {
      rep (j, w) {
        if (c[i][j] == 1) {
          ans++;
          c[i][j] = 1000;
          dfs(c, i, j);
        }
      }
    }

    cout << ans << endl;
  }
}

C++: #include<iostream>
using namespace std;
void kazoe(int p,int P, int box[50][50]){
  if(box[p][P+1]==1){
    box[p][P+1]=0;
    P=P+1;
    kazoe(p,P,box);
  }
  if(box[p+1][P+1]==1){
    box[p+1][P+1]=0;
    P=P+1;
    p=p+1;
 kazoe(p,P,box);
  }
  if(box[p+1][P]==1){
    box[p+1][P]=0;
    p=p+1;
 kazoe(p,P,box);
  }
  if(box[p+1][P-1]==1){
    box[p+1][P-1]=0;
    P=P-1;
    p=p+1;
 kazoe(p,P,box);
  }
  if(box[p][P-1]==1){
    box[p][P-1]=0;
    P=P-1;
 kazoe(p,P,box);
  }
  if(box[p-1][P-1]==1){
    box[p-1][P-1]=0;
    P=P-1;
    p=p-1;
 kazoe(p,P,box);
  }
  if(box[p-1][P]==1){
    box[p-1][P]=0;
    p=p-1;
 kazoe(p,P,box);
  }
  if(box[p-1][P+1]==1){
    box[p-1][P+1]=0;
    P=P+1;
    p=p-1;
 kazoe(p,P,box);
  }
}
int main(){
  int w,h,i,I,p,P,a=0;
  int box[50][50];
  while(1){
    cin>>w>>h;
    if(w==0&&h==0) break;
    for(i=0;i<h;i++){
      for(I=0;I<w;I++){
	cin>>box[i][I];
      }
    }
    for(i=0;i<h;i++){
      for(I=0;I<w;I++){
	if(box[i][I]==1){
	  p=i;
	  P=I;
	  box[p][P]=0;
	  kazoe(p,P,box);
	  box[i][I]=1;
	}
      }
    }
    for(i=0;i<h;i++){
      for(I=0;I<w;I++){
	if(box[i][I]==1) a++;
      }
    }
  
    cout<<a<<endl;
    a=0;
  }
  return 0;
}

C++: #include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; i < n; ++i)
#define REPR(i, n) for (int i = n - 1; i >= 0; --i)
#define FOR(i, a, b) for (int i = a; i < b; ++i)
#define FORR(i, a, b) for (int i = b - 1; i >= a; --i)
#define SORT(v) sort(v.begin(), v.end())
#define SORTR(v) sort(v.rbegin(), v.rend())
#define REV(v) reverse(v.begin(), v.end())
#define ITER(itr, v) for (auto itr = v.begin(); itr != v.end(); ++itr)
#define LB(v, x) (lower_bound(v.begin(), v.end(), x) - v.begin())
#define UB(v, x) (upper_bound(v.begin(), v.end(), x) - v.begin())
#define SZ(v) (int)v.size()
using namespace std;
using ll = long long;
using P = pair<int, int>;

class Grid {
	int h, w;
	vector<vector<int>> c;
	const int di[8] = {1, 1, 0, -1, -1, -1, 0, 1};
	const int dj[8] = {0, 1, 1, 1, 0, -1, -1, -1};

public:
	Grid(int h, int w) : h(h), w(w), c(h, vector<int>(w)) {}
	void input() {
		REP(i, h) {
			REP(j, w) {
				cin >> c[i][j];
			}
		}
	}
	int dfs(int i, int j) {
		if (c[i][j] == 0) return 0;
		c[i][j] = 0;
		REP(k, 8) {
			int u = i + di[k];
			int v = j + dj[k];
			if (u >= 0 && u < h && v >= 0 && v < w) {
				dfs(u, v);
			}
		}
		return 1;
	}
	int ans() {
		int res = 0;
		REP(i, h) {
			REP(j, w) {
				res += dfs(i, j);
			}
		}
		return res;
	}
};

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	while (true) {
		int h, w;
		cin >> w >> h;
		if (h == 0 && w == 0) break;
		Grid grid(h, w);
		grid.input();
		cout << grid.ans() << endl;
	}

	return 0;
}