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


猜你喜欢

转载自blog.csdn.net/qq_41668093/article/details/80150569