hihocoder #1487 岛屿3 并查集+搜索

版权声明:点个关注(^-^)V https://blog.csdn.net/weixin_41793113/article/details/88578422

#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 

原题链接

这里联通集我们用并查集处理一下,二维的点集,可以把x,y映射到1000x+y上构成一维的。因为xy范围都在1000内,用并查集以便于统计联通集的个数,每次放入一个新块之后,把周边的相邻的点都先存到一个vector里,然后挨着判断一下是不是一个集合,如果不是一个集合,那么联通集总数就要-1,如果不相邻,总数就+1,新增周长可以用4-2*相邻的边数来计算。

二维转变一维,我们一般写的入门并查集,都是一维,这里我们通过1005*x+y转成一维,为什么取1005呢,比1000大就行了,这里的数据规模实际大于了1000*1000,所以开大一点才可以A

import java.util.Scanner;

public class hihocoder_1487_岛屿3 {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		n = in.nextInt();
		f = new int[1005*1005+5];
		for(int i=0;i<=1005*1005;i++)
			f[i] = -1;//初始化海
		for(int i=1;i<=n;i++) {
			int a = 1005*in.nextInt()+in.nextInt();
			f[a] = a;
			insert(a, i);
		}
		
	}
	
	static int n;
	static int[] f;
	static int cnt=0,c=0;
	
	static int find(int x) {
		if(f[x]==x)//x = 1005*x+y
			return x;
		return f[x] = find(f[x]);
	}
	
	
	static void insert(int x,int m) {
		cnt++;
		int k=0;
		k+=union(x,x-1005);
		k+=union(x,x+1);
		k+=union(x,x+1005);
		k+=union(x,x-1);
		c+=4-2*k;
		System.out.println(cnt+" "+m+" "+c);
	}
	
	static int union(int x,int y) {
		if(y<0 || y>1005*1005 || f[y]==-1)
			return 0;
		int u = find(f[x]);
		int v = find(f[y]);
//		System.out.println(x+" "+y);
		if(u!=v) {
			f[u] = v;
			cnt--;
		}
		return 1;
	}	

}

猜你喜欢

转载自blog.csdn.net/weixin_41793113/article/details/88578422
今日推荐