# SP15436 UCV2013H - Slick
## 题目描述
一片大小为 $n\times m$ 的海面发生了石油泄漏,石油表示为 $1$,海水表示为 $0$。
求石油组成的连通块总数,以及每种面积连通块的个数。
**本题多测**
## 输入格式
对于每组测试数据,第一行两个整数 $n$ 和 $m$,表示海面的大小。
后跟一个 $n\times m$ 大小的字符矩阵,表示海面的石油泄漏情况。
当 $n = m = 0$ 时,终止程序。
## 输出格式
对于每组测试数据,第 $1$ 行输出一个整数 $k$,表示石油组成的连通块总数。
第 $2$ 至 $k$ 行每行两个整数 $i, j$,表示面积为 $i$ 的连通块有 $j$ 个。
**【数据范围及约定】**
对于 $100\%$ 的数据,$1 \le n, m\le250$。
Translated by @[159号程序员](https://www.luogu.com.cn/user/334586)。
## 输入输出样例 #1
### 输入 #1
```
10 10
1 1 1 1 1 1 1 1 1 1
1 1 1 1 0 0 0 0 0 0
1 1 1 0 0 0 0 1 1 1
1 1 0 0 1 0 0 1 1 1
1 0 1 0 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 1 1 1 1 1
0 0
```### 输出 #1
```
7
1 2
2 1
6 1
10 2
20 1
```
#include<bits/stdc++.h>
using namespace std;
const int N=300;
typedef pair<int,int> PII;
int n,m;
int st[N][N],ans[90010];
int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};
int cnt=0;
int bfs(int x,int y)
{
int area=1;//起始点也算面积
queue<PII> q;
q.push({x,y});
while(!q.empty())
{
auto t=q.front();
q.pop();
for(int i=0;i<4;i++)
{
int a=t.first+dx[i];
int b=t.second+dy[i];
if(a>=1&&b>=1&&a<=n&&b<=m&&st[a][b]==1)
{
//不越界且没有遍历过 就搜一遍
q.push({a,b});
st[a][b]=0,area++;
}
}
}
return area;
}
int main()
{
while(cin>>n>>m&&n&&m)
{
memset(ans,0,sizeof(ans));
memset(st,0,sizeof(st));
cnt=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>st[i][j];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(st[i][j]) //遇到1 就bfs
{
ans[bfs(i,j)]++,cnt++;
}
}
}
cout<<cnt<<endl;
for(int i=1;i<=90000;i++)
{
if(ans[i])
{
cout<<i<<" "<<ans[i]<<endl;
}
}
}
return 0;
}
总计思考:
弄了一下午不是为什么是未知错误,budong.....
但思路可以借鉴一下

被折叠的 条评论
为什么被折叠?



