2018 华中科技大学校赛 L Fresh Air BFS

链接: https://www.nowcoder.com/acm/contest/106/L
来源:牛客网

Fresh Air
时间限制:C/C++ 1秒,其他语言2秒
空间限制: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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值