hiho一下183周 Counting Island II

hiho一下183周 Counting Island II

题目原文

Country H is going to carry out a huge artificial islands project. The project region is divided into a 1000x1000 grid. The whole project will last for N weeks. Each week one unit area of sea will be filled with land.

As a result, new islands (an island consists of all connected land in 4 -- up, down, left and right -- directions) emerges in this region. Suppose the coordinates of the filled units are (0, 0), (1, 1), (1, 0). Then after the first week there is one island:  

#...
....
....
....

After the second week there are two islands:  

#...
.#..
....
....

After the three week the two previous islands are connected by the newly filled land and thus merge into one bigger island:

#...
##..
....
....

Your task is track the number of islands after each week's land filling.  

输入

The first line contains an integer N denoting the number of weeks. (1 ≤ N ≤ 100000)  

Each of the following N lines contains two integer x and y denoting the coordinates of the filled area.  (0 ≤ x, y < 1000)

输出

For each week output the number of islands after that week's land filling.

样例输入
3  
0 0   
1 1   
1 0   
样例输出
1  
2  
1  

题意分析

向坐标点0<=x<1000,0<=y<1000的位置放置land,每个星期放置一个,输入总的星期数以及每个星期放入land的坐标,输出每周放置完之后孤立岛的个数。

解法分析

本题是一个典型并查集问题,对于每周加入的点,首先让res加一,需要查它上下左右四个点,如果有点已经变成land,且属于某个island(集合),则将新加入的点并入该集合,修改其parent,res减一。遍历到下一个邻点,如果他们的root相同,则再次并为一个集合,同时res减一,直到遍历完所有四个邻点。当然,如果root相同则不需要做任何操作,如果周边点不是land(记录每一个点的count,只要加入为land就为1,在并的过程中也需要将count小的并入大的),即count=0,则不进行任何操作,同时注意周边点的坐标不能越界。C++代码如下:

#include<iostream>
#include<unordered_map>
#include<string>
#include<vector>
#include<utility>
#include<cstring>
using namespace std;
pair<int,int> myFind(int x,int y,vector<vector<pair<int,int>>> &parent){
    if(parent[x][y]==make_pair(x,y))
        return parent[x][y];
    else
        return myFind(parent[x][y].first,parent[x][y].second,parent);

}
int main(){
    vector<vector<pair<int,int>>> parent(1000,vector<pair<int,int>>(1000,make_pair(0,0)));
    int i,j;
    for(i=0;i<1000;i++){
        for(j=0;j<1000;j++)
            parent[i][j]=make_pair(i,j);
    }
    vector<vector<int>> count(1000,vector<int>(1000,0));

    int N;
    cin>>N;
    int x,y;
    int res=0;
    pair<int,int> root1,root2;
    int x1[4]={-1,1,0,0};//the four directions
    int y1[4]={0,0,-1,1};
    while(N>0){
        cin>>x>>y;
        res++;
        count[x][y]=1;//this is a land
        for(i=0;i<4;i++)
        {
            if((x+x1[i])>=0&&(x+x1[i])<1000&&(y+y1[i])>=0&&(y+y1[i])<1000&&count[x+x1[i]][y+y1[i]]>0)
            {
                root1=myFind(x,y,parent);
                root2=myFind(x+x1[i],y+y1[i],parent);
                if(root1!=root2)//if root1==root2,just continue;
                {
                    res--;
                    if(count[root1.first][root1.second]>count[root2.first][root2.second])
                    {
                        count[root1.first][root1.second]+=count[root2.first][root2.second];
                        parent[root2.first][root2.second]=make_pair(root1.first,root1.second);
                    }
                    else
                    {
                        count[root2.first][root2.second]+=count[root1.first][root1.second];
                        parent[root1.first][root1.second]=make_pair(root2.first,root2.second);
                    }
                }
            }
        }
        cout<<res<<endl;
        N--;
    }
    return 0;
}
代码中遍历四个邻点用了x1,y1两个数组,简化代码。parent用的二维vector,不可以直接定义parent[1000][1000],这样会造成栈溢出,可以用new放入堆中。这里还可以将坐标x,y用1000x+y转化为一个数,则只需要用一维数组。



               
   



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值