链接:
https://www.nowcoder.com/acm/contest/106/L
来源:牛客网
来源:牛客网
Fresh Air
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
It’s universally acknowledged that there’re innumerable trees in the campus of HUST.
And you know that, trees have the special ability to refresh the air. If an area, which is surrounded by trees, is separated from the outer atmosphere, you can call it “the supercalifragilisticexpialidocious area”. Students can enjoy the healthiest air there. Then, you happened to know that HUST will plant N trees in a bare plain, so you want to calculate the total size of “the supercalifragilisticexpialidocious area” after each operation.
We describe the position of trees with a coordinate.(X
i,Y
i).
For example, after 9 trees were planted, the green area is a supercalifragilisticexpialidocious area, its size is 3.
After planting a new tree in (3,2), its size is 2.
输入描述:
The first line is an integer N
as described above.
Then following N lines, each line contains two integer X
i and Y
i, indicating a new tree is planted at (X
i,Y
i)
.
输出描述:Output N lines, each line a integer indicating the total size of supercalifragilisticexpialidocious areas after each operation.
题意:计算被树围起来的区域大小
思路:反向DFS,一开始先把所以树种好,再一颗一颗拔掉遍历一遍;
AC代码:
#include <algorithm>
#include <string.h>
#include <cstring>
#include <stdio.h>
#include <queue>
using namespace std;
struct NODE{int x,y;}a[100005];
//supercalifragilisticexpialidocious area被树围住 从外部无法到达
//cnt为无法到达的区域大小 无法到达的区域设为0
int n,cnt,G[2005][2005],ans[100005];
int mov[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
bool bound(int x,int y)
{
return x<0||x>2000||y<0||y>2000;
}
void bfs(int x,int y)
{
/// bfs过程中 遇到1就停止
/// 能从该点出发而到达的0都变为2 无法到达的0则不变
queue <NODE> q;
q.push((NODE){x,y});
G[x][y]=2; cnt--;
while(!q.empty())
{
NODE tmp=q.front(); q.pop();
for(int i=0;i<4;i++)
{
int nowx=tmp.x+mov[i][0],
nowy=tmp.y+mov[i][1];
if(bound(nowx,nowy)) continue;//越界
if(G[nowx][nowy]) continue;//能到达或已访问过
G[nowx][nowy]=2; cnt--; //该点为能够到达的0 cnt--即去掉该点
q.push((NODE){nowx,nowy});
}
}
}
bool check(int x,int y)
{
for(int i=0;i<4;i++)
{ // 若存在因该点的树而停止继续搜索的情况
int nowx=x+mov[i][0],
nowy=y+mov[i][1];
if(bound(nowx,nowy)) continue;//越界
if(G[nowx][nowy]==2) return 1;
///即该点四周有bfs时被变为2的点
}
return 0;
}
int main ()
{
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
a[i].x+=1000, a[i].y+=1000;
G[a[i].x][a[i].y]=1;///标记1为树 2为空地;
}
cnt=2001*2001-n;
bfs(0,0);//先bfs一遍
///此时res等于减去1和2后余下的无法到达的0的个数
for(int i=n;i>0;i--) //从最后一点向前遍历
{
ans[i]=cnt++;
G[a[i].x][a[i].y]=0; ///删除该点放置的树
if(check(a[i].x,a[i].y))
bfs(a[i].x,a[i].y); //从该点继续bfs
}
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}
return 0;
}