[Offer收割]编程练习赛11 1487 岛屿3

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

H国正在进行一项持续N周的填海造岛工程。整片工程海域可以被看作是1000x1000的网格。

每周都有一块1x1的单位方格海域被填成陆地。如果我们将连成一片的陆地(一块单位方格与它上下左右4个单位方格是相连的)视为岛屿,H国想监测每周末整片海域中一共存在有多少个岛屿,以及这些岛屿的总面积和总周长各是多少。

假设工程持续三周,第一周被填的海域坐标是(0, 0),那么第一周结束后有1座岛屿、总面积是1、总周长是4:

#..
...
...

第二周被填的海域坐标是(1, 1),那么第二周结束后有2座岛屿、总面积是2、总周长是8:

#..
.#.
...

第三周被填的海域坐标是(1, 0),那么第三周结束后有1座岛屿、总面积是3、总周长是8:

#..
##.
...

你能完成这项任务么?
输入

第一行包含一个整数N,表示工程持续的周数。(1 <= N <= 100000)

以下N行每行包含两个整数x和y,表示当周被填的海域坐标。(0 <= x, y < 1000)
输出

输出N行,每行包含3个整数,依次是当周末岛屿的数量、总面积和总周长。
样例输入

3  
0 0   
1 1   
1 0

样例输出

1 1 4  
2 2 8  
1 3 8 

面积和周长都很简单, 就是岛屿的数量比较麻烦。可以用并查集,对于n个岛屿,经过合并后剩下岛屿的数量等于n减去合并次数。
代码如下:

#include<bits/stdc++.h>
using namespace std;

const int N = 1070;
int par[1010*1010], Rank[1010*1010];
char mp[1007][1007];
int dir[4][2] = { {1, 0}, {-1, 0}, {0, 1}, {0, -1}};
int many = 0;

void init()
{
    memset(mp, '.', sizeof(mp));
    for(int i=0; i<1010*1010; ++ i)
        par[i] = i, Rank[i] = 0;
}

int Find(int x)
{
    if(x == par[x])
        return x;
    return par[x] = Find(par[x]);
}

void unite(int x, int y)
{
    x = Find(x), y = Find(y);
    if(Rank[x] > Rank[y])
        par[y] = x;
    else
    {
        par[x] = y;
        if(Rank[x] == Rank[y])
            Rank[y] ++;
    }
}

int solve(int x, int y)
{
    mp[x][y] = '#';

    int res = 0;
    for(int i=0; i<4; ++ i)
    {
        int s = x + dir[i][0], t = y + dir[i][1];
        if(s >= 0 && t >= 0 && mp[s][t] == '#')
        {
            if(Find(s*1005+t) != Find(x*1005+y))
            {
                many ++;
                unite(s*1005+t, x*1005+y);
            }
            res ++;
        }
    }
    if(res == 0)
        return 4;
    if(res == 1)
        return 2;
    if(res == 2)
        return 0;
    if(res == 3)
        return -2;
    if(res == 4)
        return -4;
}

int main()
{
    ios::sync_with_stdio(false);

    init();
    int n;
    cin >> n;
    int g = 0;
    for(int i=1; i<=n; ++ i)
    {
        int x, y;
        cin >> x >> y;
        g += solve(x, y);
        cout << i-many << " " << i << " " << g << endl;
    }
    return 0;
}

posted @ 2017-03-26 17:12  aiterator  阅读(194)  评论(0编辑  收藏  举报